IBR-DTNSuite  0.10
AES128Stream.cpp
Go to the documentation of this file.
1 /*
2  * AES128Stream.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
23 #include "ibrcommon/Logger.h"
24 #include <openssl/rand.h>
25 #include <netinet/in.h>
26 
27 namespace ibrcommon
28 {
29  AES128Stream::AES128Stream(const CipherMode mode, std::ostream& output, const unsigned char key[key_size_in_bytes], const uint32_t salt)
30  : CipherStream(output, mode)
31  {
32  // init gcm and load the key into the context
33  if (gcm_init_and_key(key, key_size_in_bytes, &_ctx))
34  IBRCOMMON_LOGGER_TAG("AES128Stream", critical) << "failed to initialize aes gcm context" << IBRCOMMON_LOGGER_ENDL;
35 
36  // convert the salt to network byte order
37  _gcm_iv.salt = htonl(salt);
38 
39  // generate a random IV
40  if (!RAND_bytes(_gcm_iv.initialisation_vector, iv_len))
41  IBRCOMMON_LOGGER_TAG("AES128Stream", critical) << "failed to create initialization vector" << IBRCOMMON_LOGGER_ENDL;
42 
43  // copy the IV to a local array
44  for (unsigned int i = 0; i < iv_len; ++i)
45  _used_initialisation_vector[i] = _gcm_iv.initialisation_vector[i];
46 
47  // init the GCM message
48  gcm_init_message(reinterpret_cast<unsigned char *>(&_gcm_iv), sizeof(gcm_iv), &_ctx);
49  }
50 
51  AES128Stream::AES128Stream(const CipherMode mode, std::ostream& output, const unsigned char key[key_size_in_bytes], const uint32_t salt, const unsigned char iv[iv_len])
52  : CipherStream(output, mode)
53  {
54  // init gcm and load the key into the context
55  if (gcm_init_and_key(key, key_size_in_bytes, &_ctx))
56  IBRCOMMON_LOGGER_TAG("AES128Stream", critical) << "failed to initialize aes gcm context" << IBRCOMMON_LOGGER_ENDL;
57 
58  // convert the salt to network byte order
59  _gcm_iv.salt = htonl(salt);
60 
61  // copy the IV to local variables
62  for (unsigned int i = 0; i < iv_len; ++i)
63  {
64  _gcm_iv.initialisation_vector[i] = iv[i];
65  _used_initialisation_vector[i] = iv[i];
66  }
67 
68  // init the GCM message
69  gcm_init_message(reinterpret_cast<unsigned char *>(&_gcm_iv), sizeof(gcm_iv), &_ctx);
70  }
71 
73  {
74  // close the GCM context
75  gcm_end(&_ctx);
76  }
77 
78  void AES128Stream::getIV(unsigned char (&to_iv)[iv_len]) const
79  {
80  for (unsigned int i = 0; i < iv_len; ++i)
81  to_iv[i] = _used_initialisation_vector[i];
82  }
83 
84  void AES128Stream::getTag(unsigned char (&to_tag)[tag_len])
85  {
86  ret_type rr = gcm_compute_tag((unsigned char*)to_tag, tag_len, &_ctx);
87 
88  if (rr != RETURN_OK)
89  throw ibrcommon::Exception("tag generation failed");
90  }
91 
92  bool AES128Stream::verify(const unsigned char (&verify_tag)[tag_len])
93  {
94  try {
95  // compute the current tag
96  unsigned char tag[tag_len]; getTag(tag);
97 
98  // compare the tags
99  return (::memcmp(tag, verify_tag, tag_len) == 0);
100  } catch (const ibrcommon::Exception&) {
101  return false;
102  }
103  }
104 
105  void AES128Stream::encrypt(char *buf, const size_t size)
106  {
107  gcm_encrypt(reinterpret_cast<unsigned char *>(buf), size, &_ctx);
108  }
109 
110  void AES128Stream::decrypt(char *buf, const size_t size)
111  {
112  gcm_decrypt(reinterpret_cast<unsigned char *>(buf), size, &_ctx);
113  }
114 }