summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjhurst <jhurst@cinecert.com>2007-02-15 06:07:32 +0000
committerjhurst <>2007-02-15 06:07:32 +0000
commit7470b55c9d987d8a6d4b47bb1925c4e6eaa80afe (patch)
treecffc1d85ef40985c7a8215d30ae6b96ccc9ae440
parent2d0f4af2b7815eed9bdc1292f9059025eb2380d7 (diff)
final fixes to 429-6 HMAC
-rwxr-xr-xREADME3
-rwxr-xr-xfips-186-rng.cpp120
-rwxr-xr-xsrc/AS_DCP_AES.cpp75
-rwxr-xr-xsrc/KM_prng.cpp65
-rwxr-xr-xsrc/KM_prng.h3
-rwxr-xr-xsrc/fips-186-rng-test.cpp2
6 files changed, 75 insertions, 193 deletions
diff --git a/README b/README
index 926f521..5bea8a4 100755
--- a/README
+++ b/README
@@ -114,6 +114,9 @@ utilities all respond to -h and there are manual pages in man/.
Change History
xxx.xx.xx - Bug fixes v1.1.13
+ o Fixed SMPTE 429-6 HMAC -- FIPS 186-2 implementation was
+ laughably incorrect, thanks to Doremi for pointing this
+ out.
o Removed default parameter to HMACContext::InitKey().
o Cleaned up messages and CLI arg handling in asdcp-test.
diff --git a/fips-186-rng.cpp b/fips-186-rng.cpp
deleted file mode 100755
index c47dccb..0000000
--- a/fips-186-rng.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-Copyright (c) 2007, John Hurst
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
- /*! \file KM_prng.cpp
- \version $Id$
- \brief Fortuna pseudo-random number generator
- */
-
-
-#include <KM_prng.h>
-#include <openssl/sha.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-
-using namespace Kumu;
-
-
-//
-// SMPTE 429.6 MIC key generation
-void
-Kumu::Gen_FIPS_186_Value(const byte_t* key, byte_t* out_value)
-{
- // FIPS 186-2 Sec. 3.1 as modified by Change 1, section entitled "General Purpose Random Number Generation"
- //
- byte_t sha_buf0[SHA_DIGEST_LENGTH];
- byte_t sha_buf1[SHA_DIGEST_LENGTH];
- byte_t key2[64];
- SHA_CTX SHA;
- BN_CTX* ctx1 = BN_CTX_new(); // used by BN_* functions
- assert(ctx1);
-
- memset(key2, 0, 64);
- memcpy(key2, key, SHA_DIGEST_LENGTH);
- // 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, key2, 64);
-
- ui32_t* buf_p = (ui32_t*)sha_buf0;
- *buf_p++ = KM_i32_BE(SHA.h0);
- *buf_p++ = KM_i32_BE(SHA.h1);
- *buf_p++ = KM_i32_BE(SHA.h2);
- *buf_p++ = KM_i32_BE(SHA.h3);
- *buf_p++ = KM_i32_BE(SHA.h4);
- memcpy(out_value, sha_buf0, SHA_DIGEST_LENGTH);
-
- // step d ...
- BIGNUM xkey1, xkey2, x0;
- BN_init(&xkey1); BN_init(&xkey2); BN_init(&x0);
-
- BN_bin2bn(key2, SHA_DIGEST_LENGTH, &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[70]; // 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);
- memset( bin_buf, 0, 64);
- BN_bn2bin(&xkey1, bin_buf);
-
- // step c -- x = G(t,xkey)
- SHA1_Init(&SHA);
- SHA1_Update(&SHA, bin_buf, 64);
-
- buf_p = (ui32_t*)sha_buf1;
- *buf_p++ = KM_i32_BE(SHA.h0);
- *buf_p++ = KM_i32_BE(SHA.h1);
- *buf_p++ = KM_i32_BE(SHA.h2);
- *buf_p++ = KM_i32_BE(SHA.h3);
- *buf_p++ = KM_i32_BE(SHA.h4);
-
- assert(memcmp(sha_buf1, sha_buf0, SHA_DIGEST_LENGTH) != 0); // are x0 and x1 different?
-
- BN_CTX_free(ctx1);
- memcpy(out_value + SHA_DIGEST_LENGTH, sha_buf1, SHA_DIGEST_LENGTH);
-}
-
-
-//
-// end fips-186-rng.cpp
-//
diff --git a/src/AS_DCP_AES.cpp b/src/AS_DCP_AES.cpp
index 037e68d..1146bb7 100755
--- a/src/AS_DCP_AES.cpp
+++ b/src/AS_DCP_AES.cpp
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2007, John Hurst
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ 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;
@@ -43,14 +44,6 @@ const int KEY_SIZE_BITS = 128;
#include <openssl/bn.h>
#include <openssl/err.h>
-#if OPENSSL_VERSION_NUMBER < 0x0090804f
-# error OpenSSL version mismatch
-#endif
-
-#ifndef OPENSSL_VERSION_NUMBER
-#error OPENSSL_VERSION_NUMBER not defined
-#endif
-
void
print_ssl_error()
@@ -269,67 +262,9 @@ public:
// 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);
-
- // 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);
+ byte_t rng_buf[SHA_DIGEST_LENGTH*2];
+ Kumu::Gen_FIPS_186_Value(key, KeyLen, rng_buf, SHA_DIGEST_LENGTH*2);
+ memcpy(m_key, rng_buf+SHA_DIGEST_LENGTH, KeyLen);
Reset();
}
diff --git a/src/KM_prng.cpp b/src/KM_prng.cpp
index e710d9a..65c4656 100755
--- a/src/KM_prng.cpp
+++ b/src/KM_prng.cpp
@@ -36,6 +36,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assert.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
+#include <openssl/bn.h>
using namespace Kumu;
@@ -146,7 +147,7 @@ static h__RNG* s_RNG = 0;
//------------------------------------------------------------------------------------------
//
-// public interface
+// Fortuna public interface
Kumu::FortunaRNG::FortunaRNG()
{
@@ -190,6 +191,68 @@ Kumu::FortunaRNG::FillRandom(Kumu::ByteString& Buffer)
return Buffer.Data();
}
+//------------------------------------------------------------------------------------------
+
+//
+// FIPS 186-2 Sec. 3.1 as modified by Change 1, section entitled "General Purpose Random Number Generation"
+void
+Kumu::Gen_FIPS_186_Value(const byte_t* key, ui32_t key_size, byte_t* out_buf, ui32_t out_buf_len)
+{
+ byte_t sha_buf[SHA_DIGEST_LENGTH];
+ const ui32_t key_buf_len = 64;
+ byte_t key_buf[key_buf_len];
+ SHA_CTX SHA;
+ BN_CTX* ctx1 = BN_CTX_new(); // used by BN_* functions
+ assert(ctx1);
+
+ // init key
+ memset(key_buf, 0, key_buf_len);
+ memcpy(key_buf, key, xmin<ui32_t>(key_buf_len, key_size));
+
+ // 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);
+
+ for (;;)
+ {
+ // step c -- x = G(t,xkey)
+ SHA1_Init(&SHA);
+ SHA1_Update(&SHA, key_buf, key_buf_len);
+ ui32_t* buf_p = (ui32_t*)sha_buf;
+ *buf_p++ = KM_i32_BE(SHA.h0);
+ *buf_p++ = KM_i32_BE(SHA.h1);
+ *buf_p++ = KM_i32_BE(SHA.h2);
+ *buf_p++ = KM_i32_BE(SHA.h3);
+ *buf_p++ = KM_i32_BE(SHA.h4);
+ memcpy(out_buf, sha_buf, xmin<ui32_t>(out_buf_len, SHA_DIGEST_LENGTH));
+
+ if ( out_buf_len <= SHA_DIGEST_LENGTH )
+ break;
+
+ out_buf_len -= SHA_DIGEST_LENGTH;
+ out_buf += SHA_DIGEST_LENGTH;
+
+ // step d ...
+ BIGNUM xkey1, xkey_buf, x0;
+ BN_init(&xkey1); BN_init(&xkey_buf); BN_init(&x0);
+
+ BN_bin2bn(key_buf, SHA_DIGEST_LENGTH, &xkey1);
+ BN_bin2bn(sha_buf, SHA_DIGEST_LENGTH, &x0);
+ BN_add_word(&xkey1, 1); // xkey += 1
+ BN_add(&xkey_buf, &xkey1, &x0); // xkey += x
+ BN_mod(&xkey1, &xkey_buf, &c_2powb, ctx1); // xkey = xkey mod (2^160)
+
+ ui32_t bn_buf_len = BN_num_bytes(&xkey1);
+ assert(bn_buf_len < SHA_DIGEST_LENGTH+1);
+ memset(key_buf, 0, key_buf_len);
+ BN_bn2bin(&xkey1, key_buf);
+ }
+
+ BN_CTX_free(ctx1);
+}
//
// end KM_prng.cpp
diff --git a/src/KM_prng.h b/src/KM_prng.h
index e718475..b592988 100755
--- a/src/KM_prng.h
+++ b/src/KM_prng.h
@@ -48,7 +48,8 @@ namespace Kumu
};
- void Gen_FIPS_186_Value(const byte_t* key_in /* 20 bytes */, byte_t* r_out /* 40 bytes */);
+ // key_len must be <= 64 (larger values will be truncated)
+ void Gen_FIPS_186_Value(const byte_t* key_in, ui32_t key_len, byte_t* buf, ui32_t buf_len);
} // namespace Kumu
diff --git a/src/fips-186-rng-test.cpp b/src/fips-186-rng-test.cpp
index c26239b..887345a 100755
--- a/src/fips-186-rng-test.cpp
+++ b/src/fips-186-rng-test.cpp
@@ -74,7 +74,7 @@ main(int argc, const char** argv)
return 3;
}
- Gen_FIPS_186_Value(XKey_buf, X_buf);
+ Gen_FIPS_186_Value(XKey_buf, SHA_DIGEST_LENGTH, X_buf, SHA_DIGEST_LENGTH*2);
if ( memcmp(X_buf, X_test_buf, SHA_DIGEST_LENGTH*2) != 0 )
{