FIPS 186-2 fixes
[asdcplib.git] / src / AS_DCP_AES.cpp
index 3d3656653c82f89be794723247529b97bbc63393..6c81cade5fa207f5d7a3c844d7f8a160e5b1bea6 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004, John Hurst
+Copyright (c) 2004-2009, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -32,16 +32,19 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #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;
 
-
-#ifndef ASDCP_WITHOUT_OPENSSL
 #include <openssl/aes.h>
 #include <openssl/sha.h>
+#include <openssl/bn.h>
 #include <openssl/err.h>
 
+
 void
 print_ssl_error()
 {
@@ -50,16 +53,9 @@ print_ssl_error()
   DefaultLogSink().Error("OpenSSL: %s\n", ERR_error_string(errval, err_buf));
 }
 
-#endif
-
-
 //------------------------------------------------------------------------------------------
 
-#ifdef ASDCP_WITHOUT_OPENSSL
-class ASDCP::AESEncContext::h__AESContext
-#else
 class ASDCP::AESEncContext::h__AESContext : public AES_KEY
-#endif
 {
 public:
   byte_t m_IVec[CBC_BLOCK_SIZE];
@@ -74,12 +70,11 @@ ASDCP::AESEncContext::~AESEncContext() {}
 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;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   m_Context = new h__AESContext;
 
   if ( AES_set_encrypt_key(key, KEY_SIZE_BITS, m_Context) )
@@ -89,9 +84,6 @@ ASDCP::AESEncContext::InitKey(const byte_t* key)
     }
 
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 
@@ -101,17 +93,13 @@ ASDCP::AESEncContext::InitKey(const byte_t* key)
 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;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   memcpy(m_Context->m_IVec, i_vec, CBC_BLOCK_SIZE);
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 
@@ -120,17 +108,13 @@ ASDCP::AESEncContext::SetIVec(const byte_t* i_vec)
 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;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   memcpy(i_vec, m_Context->m_IVec, CBC_BLOCK_SIZE);
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 
@@ -139,15 +123,14 @@ ASDCP::AESEncContext::GetIVec(byte_t* i_vec) const
 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 );
 
   if ( m_Context.empty() )
     return  RESULT_INIT;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   h__AESContext* Ctx = m_Context;
   byte_t tmp_buf[CBC_BLOCK_SIZE];
   const byte_t* in_p = pt_buf;
@@ -168,19 +151,12 @@ ASDCP::AESEncContext::EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t
     }
 
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 
 //------------------------------------------------------------------------------------------
 
-#ifdef ASDCP_WITHOUT_OPENSSL
-class ASDCP::AESDecContext::h__AESContext
-#else
 class ASDCP::AESDecContext::h__AESContext : public AES_KEY
-#endif
 {
 public:
   byte_t m_IVec[CBC_BLOCK_SIZE];
@@ -195,12 +171,11 @@ ASDCP::AESDecContext::~AESDecContext() {}
 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;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   m_Context = new h__AESContext;
 
   if ( AES_set_decrypt_key(key, KEY_SIZE_BITS, m_Context) )
@@ -210,9 +185,6 @@ ASDCP::AESDecContext::InitKey(const byte_t* key)
     }
 
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
@@ -221,17 +193,13 @@ ASDCP::AESDecContext::InitKey(const byte_t* key)
 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;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   memcpy(m_Context->m_IVec, i_vec, CBC_BLOCK_SIZE);
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 // Decrypt a 16 byte block of data.
@@ -239,15 +207,14 @@ ASDCP::AESDecContext::SetIVec(const byte_t* i_vec)
 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 );
 
   if ( m_Context.empty() )
     return  RESULT_INIT;
 
-#ifndef ASDCP_WITHOUT_OPENSSL
   register h__AESContext* Ctx = m_Context;
 
   const byte_t* in_p = ct_buf;
@@ -268,41 +235,64 @@ ASDCP::AESDecContext::DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t
     }
 
   return RESULT_OK;
-#else // ASDCP_WITHOUT_OPENSSL
-  return RESULT_FAIL;
-#endif // ASDCP_WITHOUT_OPENSSL
 }
 
 //------------------------------------------------------------------------------------------
 
+static const ui32_t B_len = 64; // rfc 2104, Sec. 2
+
+static byte_t ipad[B_len] = {
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
+};
 
-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 opad[B_len] = {
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
+};
 
 class HMACContext::h__HMACContext
 {
-#ifndef ASDCP_WITHOUT_OPENSSL
   SHA_CTX m_SHA;
-#endif // ASDCP_WITHOUT_OPENSSL
-  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)
+  {
+    byte_t rng_buf[SHA_DIGEST_LENGTH*2];
+    Kumu::Gen_FIPS_186_Value(key, KeyLen, rng_buf, SHA_DIGEST_LENGTH*2);
+
+    // 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();
+  }
+
+  // MXF Interop MIC key generation
+  void SetInteropKey(const byte_t* key)
   {
     static byte_t key_nonce[KeyLen] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
                                        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
-#ifndef ASDCP_WITHOUT_OPENSSL
     byte_t sha_buf[SHA_DIGEST_LENGTH];
 
     // 7.10: MICKey = trunc( SHA1 ( key, key_nonce ) )
@@ -312,63 +302,67 @@ public:
     SHA1_Update(&SHA, key_nonce, KeyLen);
     SHA1_Final(sha_buf, &SHA);
     memcpy(m_key, sha_buf, KeyLen);
-
     Reset();
-#endif // ASDCP_WITHOUT_OPENSSL
   }
 
+  //
   void
   Reset()
   {
-#ifndef ASDCP_WITHOUT_OPENSSL
-    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[i];
 
-    SHA1_Update(&m_SHA, xor_buf, KeyLen);
-#endif // ASDCP_WITHOUT_OPENSSL
+    SHA1_Update(&m_SHA, xor_buf, B_len);
   }
 
   //
   void
   Update(const byte_t* buf, ui32_t buf_len)
   {
-#ifndef ASDCP_WITHOUT_OPENSSL
     // H(K XOR opad, H(K XOR ipad, text))
     //                             ^^^^
     SHA1_Update(&m_SHA, buf, buf_len);
-#endif // ASDCP_WITHOUT_OPENSSL
   }
 
   //
   void
   Finalize()
   {
-#ifndef ASDCP_WITHOUT_OPENSSL
-    // 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);
+
+    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[i];
+
+    SHA1_Update(&SHA, xor_buf, B_len);
 
-    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);
+    // H(K XOR opad, H(K XOR ipad, text))
+    //               ^
+    SHA1_Final(m_SHAValue, &m_SHA);
+    SHA1_Update(&SHA, m_SHAValue, HMAC_SIZE);
 
-    SHA1_Final(sha_value, &SHA);
+    // H(K XOR opad, H(K XOR ipad, text))
+    // ^
+    SHA1_Final(m_SHAValue, &SHA);
     m_Final = true;
-#endif // ASDCP_WITHOUT_OPENSSL
   }
 };
 
@@ -384,12 +378,21 @@ HMACContext::~HMACContext()
 
 //
 Result_t
-HMACContext::InitKey(const byte_t* key)
+HMACContext::InitKey(const byte_t* key, LabelSet_t SetType)
 {
-  ASDCP_TEST_NULL(key);
+  KM_TEST_NULL_L(key);
 
   m_Context = new h__HMACContext;
-  m_Context->SetKey(key);
+
+  switch ( SetType )
+    {
+    case LS_MXF_INTEROP: m_Context->SetInteropKey(key); break;
+    case LS_MXF_SMPTE:   m_Context->SetKey(key); break;
+    default:
+      m_Context = 0;
+      return RESULT_INIT;
+    }
+
   return RESULT_OK;
 }
 
@@ -407,7 +410,7 @@ HMACContext::Reset()
 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;
@@ -433,12 +436,12 @@ HMACContext::Finalize()
 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;
 }
 
@@ -447,12 +450,12 @@ HMACContext::GetHMACValue(byte_t* buf) const
 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;
 }