2 Copyright (c) 2004-2008, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /*! \file AS_DCP_AES.h
29 \brief AS-DCP library, AES wrapper
37 using Kumu::DefaultLogSink;
39 using namespace ASDCP;
40 const int KEY_SIZE_BITS = 128;
42 #include <openssl/aes.h>
43 #include <openssl/sha.h>
44 #include <openssl/bn.h>
45 #include <openssl/err.h>
52 unsigned long errval = ERR_get_error();
53 DefaultLogSink().Error("OpenSSL: %s\n", ERR_error_string(errval, err_buf));
56 //------------------------------------------------------------------------------------------
58 class ASDCP::AESEncContext::h__AESContext : public AES_KEY
61 byte_t m_IVec[CBC_BLOCK_SIZE];
65 ASDCP::AESEncContext::AESEncContext() {}
66 ASDCP::AESEncContext::~AESEncContext() {}
68 // Initializes Rijndael CBC encryption context.
69 // Returns error if the key argument is NULL.
71 ASDCP::AESEncContext::InitKey(const byte_t* key)
78 m_Context = new h__AESContext;
80 if ( AES_set_encrypt_key(key, KEY_SIZE_BITS, m_Context) )
83 return RESULT_CRYPT_INIT;
90 // Set the value of the 16 byte CBC Initialization Vector. This operation may be performed
91 // any number of times for a given key.
92 // Returns error if the i_vec argument is NULL.
94 ASDCP::AESEncContext::SetIVec(const byte_t* i_vec)
96 KM_TEST_NULL_L(i_vec);
101 memcpy(m_Context->m_IVec, i_vec, CBC_BLOCK_SIZE);
106 // Retrieve the value of the 16 byte CBC Initialization Vector.
107 // Returns error if the i_vec argument is NULL.
109 ASDCP::AESEncContext::GetIVec(byte_t* i_vec) const
111 KM_TEST_NULL_L(i_vec);
116 memcpy(i_vec, m_Context->m_IVec, CBC_BLOCK_SIZE);
121 // Encrypt a 16 byte block of data.
122 // Returns error if either argument is NULL.
124 ASDCP::AESEncContext::EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size)
126 KM_TEST_NULL_L(pt_buf);
127 KM_TEST_NULL_L(ct_buf);
128 assert(block_size > 0);
129 assert( block_size % CBC_BLOCK_SIZE == 0 );
131 if ( m_Context.empty() )
134 h__AESContext* Ctx = m_Context;
135 byte_t tmp_buf[CBC_BLOCK_SIZE];
136 const byte_t* in_p = pt_buf;
137 byte_t* out_p = ct_buf;
141 // xor with the previous block
142 for ( ui32_t i = 0; i < CBC_BLOCK_SIZE; i++ )
143 tmp_buf[i] = in_p[i] ^ Ctx->m_IVec[i];
145 AES_encrypt(tmp_buf, Ctx->m_IVec, Ctx);
146 memcpy(out_p, Ctx->m_IVec, CBC_BLOCK_SIZE);
148 in_p += CBC_BLOCK_SIZE;
149 out_p += CBC_BLOCK_SIZE;
150 block_size -= CBC_BLOCK_SIZE;
157 //------------------------------------------------------------------------------------------
159 class ASDCP::AESDecContext::h__AESContext : public AES_KEY
162 byte_t m_IVec[CBC_BLOCK_SIZE];
165 ASDCP::AESDecContext::AESDecContext() {}
166 ASDCP::AESDecContext::~AESDecContext() {}
169 // Initializes Rijndael CBC decryption context.
170 // Returns error if the key argument is NULL.
172 ASDCP::AESDecContext::InitKey(const byte_t* key)
179 m_Context = new h__AESContext;
181 if ( AES_set_decrypt_key(key, KEY_SIZE_BITS, m_Context) )
184 return RESULT_CRYPT_INIT;
190 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
191 // any number of times for a given key.
192 // Returns error if the i_vec argument is NULL.
194 ASDCP::AESDecContext::SetIVec(const byte_t* i_vec)
196 KM_TEST_NULL_L(i_vec);
201 memcpy(m_Context->m_IVec, i_vec, CBC_BLOCK_SIZE);
205 // Decrypt a 16 byte block of data.
206 // Returns error if either argument is NULL.
208 ASDCP::AESDecContext::DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size)
210 KM_TEST_NULL_L(ct_buf);
211 KM_TEST_NULL_L(pt_buf);
212 assert(block_size > 0);
213 assert( block_size % CBC_BLOCK_SIZE == 0 );
215 if ( m_Context.empty() )
218 register h__AESContext* Ctx = m_Context;
220 const byte_t* in_p = ct_buf;
221 byte_t* out_p = pt_buf;
225 AES_decrypt(in_p, out_p, Ctx);
227 for ( ui32_t i = 0; i < CBC_BLOCK_SIZE; i++ )
228 out_p[i] ^= Ctx->m_IVec[i];
230 memcpy(Ctx->m_IVec, in_p, CBC_BLOCK_SIZE);
232 in_p += CBC_BLOCK_SIZE;
233 out_p += CBC_BLOCK_SIZE;
234 block_size -= CBC_BLOCK_SIZE;
240 //------------------------------------------------------------------------------------------
242 static const ui32_t B_len = 64; // rfc 2104, Sec. 2
244 static byte_t ipad[B_len] = {
245 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
246 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
247 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
248 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
249 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
250 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
251 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
252 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
255 static byte_t opad[B_len] = {
256 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
257 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
258 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
259 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
260 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
261 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
262 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
263 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
266 class HMACContext::h__HMACContext
269 byte_t m_key[KeyLen];
270 ASDCP_NO_COPY_CONSTRUCT(h__HMACContext);
273 byte_t m_SHAValue[HMAC_SIZE];
276 h__HMACContext() : m_Final(false) {}
279 // SMPTE 429.6 MIC key generation
280 void SetKey(const byte_t* key)
282 byte_t rng_buf[SHA_DIGEST_LENGTH*2];
283 Kumu::Gen_FIPS_186_Value(key, KeyLen, rng_buf, SHA_DIGEST_LENGTH*2);
284 memcpy(m_key, rng_buf+SHA_DIGEST_LENGTH, KeyLen);
288 // MXF Interop MIC key generation
289 void SetInteropKey(const byte_t* key)
291 static byte_t key_nonce[KeyLen] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
292 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
293 byte_t sha_buf[SHA_DIGEST_LENGTH];
295 // 7.10: MICKey = trunc( SHA1 ( key, key_nonce ) )
298 SHA1_Update(&SHA, key, KeyLen);
299 SHA1_Update(&SHA, key_nonce, KeyLen);
300 SHA1_Final(sha_buf, &SHA);
301 memcpy(m_key, sha_buf, KeyLen);
309 byte_t xor_buf[B_len];
310 memset(xor_buf, 0, B_len);
311 memcpy(xor_buf, m_key, KeyLen);
313 memset(m_SHAValue, 0, HMAC_SIZE);
317 // H(K XOR opad, H(K XOR ipad, text))
319 for ( ui32_t i = 0; i < B_len; i++ )
320 xor_buf[i] ^= ipad[i];
322 SHA1_Update(&m_SHA, xor_buf, B_len);
327 Update(const byte_t* buf, ui32_t buf_len)
329 // H(K XOR opad, H(K XOR ipad, text))
331 SHA1_Update(&m_SHA, buf, buf_len);
341 byte_t xor_buf[B_len];
342 memset(xor_buf, 0, B_len);
343 memcpy(xor_buf, m_key, KeyLen);
347 // H(K XOR opad, H(K XOR ipad, text))
349 for ( ui32_t i = 0; i < B_len; i++ )
350 xor_buf[i] ^= opad[i];
352 SHA1_Update(&SHA, xor_buf, B_len);
354 // H(K XOR opad, H(K XOR ipad, text))
356 SHA1_Final(m_SHAValue, &m_SHA);
357 SHA1_Update(&SHA, m_SHAValue, HMAC_SIZE);
359 // H(K XOR opad, H(K XOR ipad, text))
361 SHA1_Final(m_SHAValue, &SHA);
367 HMACContext::HMACContext()
371 HMACContext::~HMACContext()
378 HMACContext::InitKey(const byte_t* key, LabelSet_t SetType)
382 m_Context = new h__HMACContext;
386 case LS_MXF_INTEROP: m_Context->SetInteropKey(key); break;
387 case LS_MXF_SMPTE: m_Context->SetKey(key); break;
401 if ( ! m_Context.empty() )
408 HMACContext::Update(const byte_t* buf, ui32_t buf_len)
412 if ( m_Context.empty() || m_Context->m_Final )
415 m_Context->Update(buf, buf_len);
422 HMACContext::Finalize()
424 if ( m_Context.empty() || m_Context->m_Final )
427 m_Context->Finalize();
434 HMACContext::GetHMACValue(byte_t* buf) const
438 if ( m_Context.empty() || ! m_Context->m_Final )
441 memcpy(buf, m_Context->m_SHAValue, HMAC_SIZE);
448 HMACContext::TestHMACValue(const byte_t* buf) const
452 if ( m_Context.empty() || ! m_Context->m_Final )
455 return ( memcmp(buf, m_Context->m_SHAValue, HMAC_SIZE) == 0 ) ? RESULT_OK : RESULT_HMACFAIL;
461 // end AS_DCP_AES.cpp