2 Copyright (c) 2004, 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
36 using namespace ASDCP;
37 const int KEY_SIZE_BITS = 128;
40 #ifndef ASDCP_WITHOUT_OPENSSL
41 #include <openssl/aes.h>
42 #include <openssl/sha.h>
43 #include <openssl/err.h>
49 unsigned long errval = ERR_get_error();
50 DefaultLogSink().Error("OpenSSL: %s\n", ERR_error_string(errval, err_buf));
56 //------------------------------------------------------------------------------------------
58 #ifdef ASDCP_WITHOUT_OPENSSL
59 class ASDCP::AESEncContext::h__AESContext
61 class ASDCP::AESEncContext::h__AESContext : public AES_KEY
65 byte_t m_IVec[CBC_BLOCK_SIZE];
69 ASDCP::AESEncContext::AESEncContext() {}
70 ASDCP::AESEncContext::~AESEncContext() {}
72 // Initializes Rijndael CBC encryption context.
73 // Returns error if the key argument is NULL.
75 ASDCP::AESEncContext::InitKey(const byte_t* key)
82 #ifndef ASDCP_WITHOUT_OPENSSL
83 m_Context = new h__AESContext;
85 if ( AES_set_encrypt_key(key, KEY_SIZE_BITS, m_Context) )
88 return RESULT_CRYPT_INIT;
92 #else // ASDCP_WITHOUT_OPENSSL
94 #endif // ASDCP_WITHOUT_OPENSSL
98 // Set the value of the 16 byte CBC Initialization Vector. This operation may be performed
99 // any number of times for a given key.
100 // Returns error if the i_vec argument is NULL.
102 ASDCP::AESEncContext::SetIVec(const byte_t* i_vec)
104 ASDCP_TEST_NULL(i_vec);
109 #ifndef ASDCP_WITHOUT_OPENSSL
110 memcpy(m_Context->m_IVec, i_vec, CBC_BLOCK_SIZE);
112 #else // ASDCP_WITHOUT_OPENSSL
114 #endif // ASDCP_WITHOUT_OPENSSL
118 // Retrieve the value of the 16 byte CBC Initialization Vector.
119 // Returns error if the i_vec argument is NULL.
121 ASDCP::AESEncContext::GetIVec(byte_t* i_vec) const
123 ASDCP_TEST_NULL(i_vec);
128 #ifndef ASDCP_WITHOUT_OPENSSL
129 memcpy(i_vec, m_Context->m_IVec, CBC_BLOCK_SIZE);
131 #else // ASDCP_WITHOUT_OPENSSL
133 #endif // ASDCP_WITHOUT_OPENSSL
137 // Encrypt a 16 byte block of data.
138 // Returns error if either argument is NULL.
140 ASDCP::AESEncContext::EncryptBlock(const byte_t* pt_buf, byte_t* ct_buf, ui32_t block_size)
142 ASDCP_TEST_NULL(pt_buf);
143 ASDCP_TEST_NULL(ct_buf);
144 assert(block_size > 0);
145 assert( block_size % CBC_BLOCK_SIZE == 0 );
147 if ( m_Context.empty() )
150 #ifndef ASDCP_WITHOUT_OPENSSL
151 h__AESContext* Ctx = m_Context;
152 byte_t tmp_buf[CBC_BLOCK_SIZE];
153 const byte_t* in_p = pt_buf;
154 byte_t* out_p = ct_buf;
158 // xor with the previous block
159 for ( ui32_t i = 0; i < CBC_BLOCK_SIZE; i++ )
160 tmp_buf[i] = in_p[i] ^ Ctx->m_IVec[i];
162 AES_encrypt(tmp_buf, Ctx->m_IVec, Ctx);
163 memcpy(out_p, Ctx->m_IVec, CBC_BLOCK_SIZE);
165 in_p += CBC_BLOCK_SIZE;
166 out_p += CBC_BLOCK_SIZE;
167 block_size -= CBC_BLOCK_SIZE;
171 #else // ASDCP_WITHOUT_OPENSSL
173 #endif // ASDCP_WITHOUT_OPENSSL
177 //------------------------------------------------------------------------------------------
179 #ifdef ASDCP_WITHOUT_OPENSSL
180 class ASDCP::AESDecContext::h__AESContext
182 class ASDCP::AESDecContext::h__AESContext : public AES_KEY
186 byte_t m_IVec[CBC_BLOCK_SIZE];
189 ASDCP::AESDecContext::AESDecContext() {}
190 ASDCP::AESDecContext::~AESDecContext() {}
193 // Initializes Rijndael CBC decryption context.
194 // Returns error if the key argument is NULL.
196 ASDCP::AESDecContext::InitKey(const byte_t* key)
198 ASDCP_TEST_NULL(key);
203 #ifndef ASDCP_WITHOUT_OPENSSL
204 m_Context = new h__AESContext;
206 if ( AES_set_decrypt_key(key, KEY_SIZE_BITS, m_Context) )
209 return RESULT_CRYPT_INIT;
213 #else // ASDCP_WITHOUT_OPENSSL
215 #endif // ASDCP_WITHOUT_OPENSSL
218 // Initializes 16 byte CBC Initialization Vector. This operation may be performed
219 // any number of times for a given key.
220 // Returns error if the i_vec argument is NULL.
222 ASDCP::AESDecContext::SetIVec(const byte_t* i_vec)
224 ASDCP_TEST_NULL(i_vec);
229 #ifndef ASDCP_WITHOUT_OPENSSL
230 memcpy(m_Context->m_IVec, i_vec, CBC_BLOCK_SIZE);
232 #else // ASDCP_WITHOUT_OPENSSL
234 #endif // ASDCP_WITHOUT_OPENSSL
237 // Decrypt a 16 byte block of data.
238 // Returns error if either argument is NULL.
240 ASDCP::AESDecContext::DecryptBlock(const byte_t* ct_buf, byte_t* pt_buf, ui32_t block_size)
242 ASDCP_TEST_NULL(ct_buf);
243 ASDCP_TEST_NULL(pt_buf);
244 assert(block_size > 0);
245 assert( block_size % CBC_BLOCK_SIZE == 0 );
247 if ( m_Context.empty() )
250 #ifndef ASDCP_WITHOUT_OPENSSL
251 register h__AESContext* Ctx = m_Context;
253 const byte_t* in_p = ct_buf;
254 byte_t* out_p = pt_buf;
258 AES_decrypt(in_p, out_p, Ctx);
260 for ( ui32_t i = 0; i < CBC_BLOCK_SIZE; i++ )
261 out_p[i] ^= Ctx->m_IVec[i];
263 memcpy(Ctx->m_IVec, in_p, CBC_BLOCK_SIZE);
265 in_p += CBC_BLOCK_SIZE;
266 out_p += CBC_BLOCK_SIZE;
267 block_size -= CBC_BLOCK_SIZE;
271 #else // ASDCP_WITHOUT_OPENSSL
273 #endif // ASDCP_WITHOUT_OPENSSL
276 //------------------------------------------------------------------------------------------
279 static byte_t ipad[KeyLen] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
280 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 };
282 static byte_t opad[KeyLen] = { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
283 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c };
285 class HMACContext::h__HMACContext
287 #ifndef ASDCP_WITHOUT_OPENSSL
289 #endif // ASDCP_WITHOUT_OPENSSL
290 byte_t m_key[KeyLen];
291 ASDCP_NO_COPY_CONSTRUCT(h__HMACContext);
294 byte_t sha_value[HMAC_SIZE];
297 h__HMACContext() : m_Final(false) {}
301 void SetKey(const byte_t* key)
303 static byte_t key_nonce[KeyLen] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
304 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
305 #ifndef ASDCP_WITHOUT_OPENSSL
306 byte_t sha_buf[SHA_DIGEST_LENGTH];
308 // 7.10: MICKey = trunc( SHA1 ( key, key_nonce ) )
311 SHA1_Update(&SHA, key, KeyLen);
312 SHA1_Update(&SHA, key_nonce, KeyLen);
313 SHA1_Final(sha_buf, &SHA);
314 memcpy(m_key, sha_buf, KeyLen);
317 #endif // ASDCP_WITHOUT_OPENSSL
323 #ifndef ASDCP_WITHOUT_OPENSSL
324 byte_t xor_buf[KeyLen];
325 memset(sha_value, 0, HMAC_SIZE);
329 // H(K XOR opad, H(K XOR ipad, text))
331 for ( ui32_t i = 0; i < KeyLen; i++ )
332 xor_buf[i] = m_key[i] ^ ipad[i];
334 SHA1_Update(&m_SHA, xor_buf, KeyLen);
335 #endif // ASDCP_WITHOUT_OPENSSL
340 Update(const byte_t* buf, ui32_t buf_len)
342 #ifndef ASDCP_WITHOUT_OPENSSL
343 // H(K XOR opad, H(K XOR ipad, text))
345 SHA1_Update(&m_SHA, buf, buf_len);
346 #endif // ASDCP_WITHOUT_OPENSSL
353 #ifndef ASDCP_WITHOUT_OPENSSL
354 // H(K XOR opad, H(K XOR ipad, text))
356 SHA1_Final(sha_value, &m_SHA);
361 byte_t xor_buf[KeyLen];
363 for ( ui32_t i = 0; i < KeyLen; i++ )
364 xor_buf[i] = m_key[i] ^ opad[i];
366 SHA1_Update(&SHA, xor_buf, KeyLen);
367 SHA1_Update(&SHA, sha_value, HMAC_SIZE);
369 SHA1_Final(sha_value, &SHA);
371 #endif // ASDCP_WITHOUT_OPENSSL
376 HMACContext::HMACContext()
380 HMACContext::~HMACContext()
387 HMACContext::InitKey(const byte_t* key)
389 ASDCP_TEST_NULL(key);
391 m_Context = new h__HMACContext;
392 m_Context->SetKey(key);
401 if ( ! m_Context.empty() )
408 HMACContext::Update(const byte_t* buf, ui32_t buf_len)
410 ASDCP_TEST_NULL(buf);
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
436 ASDCP_TEST_NULL(buf);
438 if ( m_Context.empty() || ! m_Context->m_Final )
441 memcpy(buf, m_Context->sha_value, HMAC_SIZE);
448 HMACContext::TestHMACValue(const byte_t* buf) const
450 ASDCP_TEST_NULL(buf);
452 if ( m_Context.empty() || ! m_Context->m_Final )
455 return ( memcmp(buf, m_Context->sha_value, HMAC_SIZE) == 0 ) ? RESULT_OK : RESULT_HMACFAIL;
461 // end AS_DCP_AES.cpp