/*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2009, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
#include <assert.h>
#include <AS_DCP.h>
#include <KM_log.h>
+#include <KM_prng.h>
using Kumu::DefaultLogSink;
using namespace ASDCP;
const int KEY_SIZE_BITS = 128;
-
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/bn.h>
#include <openssl/err.h>
+
void
print_ssl_error()
{
class ASDCP::AESEncContext::h__AESContext : public AES_KEY
{
public:
+ Kumu::SymmetricKey m_KeyBuf;
byte_t m_IVec[CBC_BLOCK_SIZE];
};
ASDCP::Result_t
ASDCP::AESEncContext::InitKey(const byte_t* key)
{
- ASDCP_TEST_NULL(key);
+ KM_TEST_NULL_L(key);
if ( m_Context )
return RESULT_INIT;
m_Context = new h__AESContext;
+ m_Context->m_KeyBuf.Set(key);
- if ( AES_set_encrypt_key(key, KEY_SIZE_BITS, m_Context) )
+ if ( AES_set_encrypt_key(m_Context->m_KeyBuf.Value(), KEY_SIZE_BITS, m_Context) )
{
print_ssl_error();
return RESULT_CRYPT_INIT;
ASDCP::Result_t
ASDCP::AESEncContext::SetIVec(const byte_t* i_vec)
{
- ASDCP_TEST_NULL(i_vec);
+ KM_TEST_NULL_L(i_vec);
if ( ! m_Context )
return RESULT_INIT;
ASDCP::Result_t
ASDCP::AESEncContext::GetIVec(byte_t* i_vec) const
{
- ASDCP_TEST_NULL(i_vec);
+ KM_TEST_NULL_L(i_vec);
if ( ! m_Context )
return RESULT_INIT;
ASDCP::Result_t
ASDCP::AESEncContext::EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size)
{
- ASDCP_TEST_NULL(pt_buf);
- ASDCP_TEST_NULL(ct_buf);
+ KM_TEST_NULL_L(pt_buf);
+ KM_TEST_NULL_L(ct_buf);
assert(block_size > 0);
assert( block_size % CBC_BLOCK_SIZE == 0 );
class ASDCP::AESDecContext::h__AESContext : public AES_KEY
{
public:
+ Kumu::SymmetricKey m_KeyBuf;
byte_t m_IVec[CBC_BLOCK_SIZE];
};
ASDCP::Result_t
ASDCP::AESDecContext::InitKey(const byte_t* key)
{
- ASDCP_TEST_NULL(key);
+ KM_TEST_NULL_L(key);
if ( m_Context )
return RESULT_INIT;
m_Context = new h__AESContext;
+ m_Context->m_KeyBuf.Set(key);
- if ( AES_set_decrypt_key(key, KEY_SIZE_BITS, m_Context) )
+ if ( AES_set_decrypt_key(m_Context->m_KeyBuf.Value(), KEY_SIZE_BITS, m_Context) )
{
print_ssl_error();
return RESULT_CRYPT_INIT;
ASDCP::Result_t
ASDCP::AESDecContext::SetIVec(const byte_t* i_vec)
{
- ASDCP_TEST_NULL(i_vec);
+ KM_TEST_NULL_L(i_vec);
if ( ! m_Context )
return RESULT_INIT;
ASDCP::Result_t
ASDCP::AESDecContext::DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size)
{
- ASDCP_TEST_NULL(ct_buf);
- ASDCP_TEST_NULL(pt_buf);
+ KM_TEST_NULL_L(ct_buf);
+ KM_TEST_NULL_L(pt_buf);
assert(block_size > 0);
assert( block_size % CBC_BLOCK_SIZE == 0 );
//------------------------------------------------------------------------------------------
+static const ui32_t B_len = 64; // rfc 2104, Sec. 2
-static byte_t ipad[KeyLen] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 };
-
-static byte_t opad[KeyLen] = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c };
+static byte_t const ipad_const = 0x36;
+static byte_t const opad_const = 0x5c;
class HMACContext::h__HMACContext
{
SHA_CTX m_SHA;
- byte_t m_key[KeyLen];
+ byte_t m_key[KeyLen];
ASDCP_NO_COPY_CONSTRUCT(h__HMACContext);
public:
- byte_t sha_value[HMAC_SIZE];
- bool m_Final;
+ byte_t m_SHAValue[HMAC_SIZE];
+ bool m_Final;
h__HMACContext() : m_Final(false) {}
~h__HMACContext() {}
// SMPTE 429.6 MIC key generation
void SetKey(const byte_t* key)
{
- // FIPS 186-2 Sec. 3.1 as modified by Change 1, section entitled "General Purpose Random Number Generation"
- //
-
- static byte_t t[SHA_DIGEST_LENGTH] = {
- 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89,
- 0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76,
- 0xc3, 0xd2, 0xe1, 0xf0
- };
-
- byte_t sha_buf0[SHA_DIGEST_LENGTH];
- byte_t sha_buf1[SHA_DIGEST_LENGTH];
- SHA_CTX SHA;
- BN_CTX* ctx1 = BN_CTX_new(); // used by BN_* functions
- assert(ctx1);
-
- // create the 2^160 constant
- BIGNUM c_2powb, c_2, c_160;
- BN_init(&c_2powb); BN_init(&c_2); BN_init(&c_160);
- BN_set_word(&c_2, 2);
- BN_set_word(&c_160, 160);
- BN_exp(&c_2powb, &c_2, &c_160, ctx1);
-
- // ROUND 1
- // step a -- SMPTE 429.6 sets XSEED = 0, so no need to do anything for this step
- // step b -- (key mod 2^160) is moot because the input value is only 128 bits in length
-
- // step c -- x = G(t,xkey)
- SHA1_Init(&SHA);
- SHA1_Update(&SHA, t, SHA_DIGEST_LENGTH);
- SHA1_Update(&SHA, key, KeyLen);
- SHA1_Final(sha_buf0, &SHA);
-
- // step d ...
- BIGNUM xkey1, xkey2, x0;
- BN_init(&xkey1); BN_init(&xkey2); BN_init(&x0);
-
- BN_bin2bn(key, KeyLen, &xkey1);
- BN_bin2bn(sha_buf0, SHA_DIGEST_LENGTH, &x0);
- BN_add_word(&xkey1, 1); // xkey += 1
- BN_add(&xkey2, &xkey1, &x0); // xkey += x
- BN_mod(&xkey1, &xkey2, &c_2powb, ctx1); // xkey = xkey mod (2^160)
-
- // ROUND 2
- // step a -- SMPTE 429.6 sets XSEED = 0, so no need to do anything for this step
- // step b -- (key mod 2^160) is moot because xkey1 is the result of the same operation
-
- byte_t bin_buf[SHA_DIGEST_LENGTH+1]; // we need xkey1 in bin form for use by SHA1_Update
- ui32_t bin_buf_len = BN_num_bytes(&xkey1);
- assert(bin_buf_len < SHA_DIGEST_LENGTH+1);
- BN_bn2bin(&xkey1, bin_buf);
+ byte_t rng_buf[SHA_DIGEST_LENGTH*2];
+ Kumu::Gen_FIPS_186_Value(key, KeyLen, rng_buf, SHA_DIGEST_LENGTH*2);
- // step c -- x = G(t,xkey)
- SHA1_Init(&SHA);
- SHA1_Update(&SHA, t, SHA_DIGEST_LENGTH);
- SHA1_Update(&SHA, bin_buf, bin_buf_len);
- SHA1_Final(sha_buf1, &SHA);
-
- assert(memcmp(sha_buf1, sha_buf0, SHA_DIGEST_LENGTH) != 0); // are x0 and x1 different?
-
- BN_CTX_free(ctx1);
- memcpy(m_key, sha_buf1, KeyLen);
+ // rng_buf contains two rounds, x0 and x1 (each 160 bits).
+ // Use x1 per SMPTE 430-6-2006 Sec. 7.10
+ memcpy(m_key, rng_buf+SHA_DIGEST_LENGTH, KeyLen);
Reset();
}
SHA1_Update(&SHA, key_nonce, KeyLen);
SHA1_Final(sha_buf, &SHA);
memcpy(m_key, sha_buf, KeyLen);
-
Reset();
}
+ //
void
Reset()
{
- byte_t xor_buf[KeyLen];
- memset(sha_value, 0, HMAC_SIZE);
+ byte_t xor_buf[B_len];
+ memset(xor_buf, 0, B_len);
+ memcpy(xor_buf, m_key, KeyLen);
+
+ memset(m_SHAValue, 0, HMAC_SIZE);
m_Final = false;
SHA1_Init(&m_SHA);
// H(K XOR opad, H(K XOR ipad, text))
// ^^^^^^^^^^
- for ( ui32_t i = 0; i < KeyLen; i++ )
- xor_buf[i] = m_key[i] ^ ipad[i];
+ for ( ui32_t i = 0; i < B_len; i++ )
+ xor_buf[i] ^= ipad_const;
- SHA1_Update(&m_SHA, xor_buf, KeyLen);
+ SHA1_Update(&m_SHA, xor_buf, B_len);
}
//
void
Finalize()
{
- // H(K XOR opad, H(K XOR ipad, text))
- // ^^^^^^^^^^^^^^^
- SHA1_Final(sha_value, &m_SHA);
-
SHA_CTX SHA;
SHA1_Init(&SHA);
- byte_t xor_buf[KeyLen];
+ byte_t xor_buf[B_len];
+ memset(xor_buf, 0, B_len);
+ memcpy(xor_buf, m_key, KeyLen);
- for ( ui32_t i = 0; i < KeyLen; i++ )
- xor_buf[i] = m_key[i] ^ opad[i];
-
- SHA1_Update(&SHA, xor_buf, KeyLen);
- SHA1_Update(&SHA, sha_value, HMAC_SIZE);
+ SHA1_Init(&SHA);
+
+ // H(K XOR opad, H(K XOR ipad, text))
+ // ^^^^^^^^^^
+ for ( ui32_t i = 0; i < B_len; i++ )
+ xor_buf[i] ^= opad_const;
+
+ SHA1_Update(&SHA, xor_buf, B_len);
- SHA1_Final(sha_value, &SHA);
+ // H(K XOR opad, H(K XOR ipad, text))
+ // ^
+ SHA1_Final(m_SHAValue, &m_SHA);
+ SHA1_Update(&SHA, m_SHAValue, HMAC_SIZE);
+
+ // H(K XOR opad, H(K XOR ipad, text))
+ // ^
+ SHA1_Final(m_SHAValue, &SHA);
m_Final = true;
}
};
Result_t
HMACContext::InitKey(const byte_t* key, LabelSet_t SetType)
{
- ASDCP_TEST_NULL(key);
+ KM_TEST_NULL_L(key);
m_Context = new h__HMACContext;
Result_t
HMACContext::Update(const byte_t* buf, ui32_t buf_len)
{
- ASDCP_TEST_NULL(buf);
+ KM_TEST_NULL_L(buf);
if ( m_Context.empty() || m_Context->m_Final )
return RESULT_INIT;
Result_t
HMACContext::GetHMACValue(byte_t* buf) const
{
- ASDCP_TEST_NULL(buf);
+ KM_TEST_NULL_L(buf);
if ( m_Context.empty() || ! m_Context->m_Final )
return RESULT_INIT;
- memcpy(buf, m_Context->sha_value, HMAC_SIZE);
+ memcpy(buf, m_Context->m_SHAValue, HMAC_SIZE);
return RESULT_OK;
}
Result_t
HMACContext::TestHMACValue(const byte_t* buf) const
{
- ASDCP_TEST_NULL(buf);
+ KM_TEST_NULL_L(buf);
if ( m_Context.empty() || ! m_Context->m_Final )
return RESULT_INIT;
- return ( memcmp(buf, m_Context->sha_value, HMAC_SIZE) == 0 ) ? RESULT_OK : RESULT_HMACFAIL;
+ return ( memcmp(buf, m_Context->m_SHAValue, HMAC_SIZE) == 0 ) ? RESULT_OK : RESULT_HMACFAIL;
}