KJB
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
wrap_openssl_evp.h
Go to the documentation of this file.
1 
8 /*
9  * $Id: wrap_openssl_evp.h 17473 2014-09-08 01:22:34Z predoehl $
10  */
11 
12 #ifndef OPENSSL_CPP_EVP_H_WRAP_PREDOEHL_UOFARIZONA_VISION
13 #define OPENSSL_CPP_EVP_H_WRAP_PREDOEHL_UOFARIZONA_VISION
14 
15 #include <l_cpp/l_exception.h>
16 
17 #ifdef KJB_HAVE_OPENSSL
18 #include <openssl/evp.h>
19 #else
20 #warning "OpenSSL is required for class OpenSSL_EVP to function properly"
21 #endif
22 
23 #include <vector>
24 
25 
26 namespace kjb
27 {
28 
35 {
36 
37 public:
39  typedef unsigned char Unit;
40 
42  typedef std::vector< Unit > Digest;
43 
44 private:
45 
46 #ifdef KJB_HAVE_OPENSSL
47  EVP_MD_CTX m_context;
48 #endif
49 
50  Digest m_digest;
51  bool m_finalized;
52 
53  void finalize(); // not very long, but too long (I deem) to inline a lot
54 
55  void safe_finalize()
56  {
57  /*
58  * I'd like to write this like so: m_finalized || finalize();
59  * but that would be poor sport.
60  */
61  if ( ! m_finalized )
62  {
63  finalize();
64  }
65  }
66 
67 #ifdef KJB_HAVE_OPENSSL
68  void update( const void* data, unsigned long len )
69  {
70  ETX_2( m_finalized, "Cannot write to an already-finalized digest");
71  ETX( 0 == EVP_DigestUpdate( &m_context, data, len ) );
72  }
73 #else
74  /*
75  * Since the class cannot be instantiated, you never get to here.
76  * Unless something is horribly wrong, in which case, say that.
77  *
78  * If we had parameter names in the param list, it would cause warnings.
79  */
80  void update( const void*, unsigned long )
81  {
82  using namespace kjb_c;
83  SET_CANT_HAPPEN_BUG();
84  }
85 #endif
86 
87  /* We decline to make this copyable, because then we would need to store
88  * the algorithm selection as an extra field, and we don't want to.
89  */
90  OpenSSL_EVP( const OpenSSL_EVP& ); // copy ctor teaser
91  OpenSSL_EVP& operator=( const OpenSSL_EVP& ); // assignment teaser
92 
93 public:
103 #ifdef KJB_HAVE_OPENSSL
104  OpenSSL_EVP( const EVP_MD* algorithm )
105  : m_digest( EVP_MAX_MD_SIZE ), // strategy: allocate extra, shrink later
106  m_finalized( false )
107  {
108  EVP_MD_CTX_init( &m_context );
109  ETX( 0 == EVP_DigestInit_ex( &m_context, algorithm, 00 ) );
110  m_digest.resize( EVP_MD_CTX_size( &m_context ) );// it is later; shrink
111  // I want to do all the memory allocation for m_digest at its ctor time
112  }
113 #else
115  : m_finalized( true )
116  {
118  "Missing OpenSSL -- cannot instantiate kjb::OpenSSL_EVP");
119  }
120 #endif
121 
124  {
125 #ifdef KJB_HAVE_OPENSSL
126  EVP_MD_CTX_cleanup( &m_context );
127 #endif
128  }
129 
135  void write( const void* data, unsigned long len )
136  {
137  // update will call you out if the object is already finalized
138  update( data, len );
139  }
140 
142  template< typename T >
143  void put( const T& datum )
144  {
145  write( (const void*) & datum, sizeof( T ) );
146  }
147 
149  template< typename SeqIterator >
150  void write( SeqIterator begin, SeqIterator end )
151  {
152  // I wanted to use std::for_each but I couldn't build the req. functor.
153  // To me it was trickier than at first it looked, b/c put is a template
154  for( SeqIterator ppp = begin; ppp != end; )
155  put( *ppp++ );
156  }
157 
158  // Digest-getter methods =================================
159 
161  size_t size() const
162  {
163  return m_digest.size();
164  }
165 
168  {
169  safe_finalize();
170  return m_digest; // return by value is OK because it is not very big
171  }
172 
174  Unit operator[]( size_t index )
175  {
176  safe_finalize();
177  return m_digest.at( index );
178  }
179 
181  Digest::const_iterator begin()
182  {
183  safe_finalize();
184  return m_digest.begin();
185  }
186 
188  Digest::const_iterator end()
189  {
190  safe_finalize(); // adds to the cost a bit but makes the class safer
191  return m_digest.end();
192  }
193 
195  bool is_finalized() const
196  {
197  return m_finalized;
198  }
199 };
200 
201 
202 } // end namespace kjb
203 
204 #endif
205 
Unit operator[](size_t index)
Access one character of the message digest.
Definition: wrap_openssl_evp.h:174
Generic OpenSSL hasher class, the base class for specific derivations.
Definition: wrap_openssl_evp.h:34
#define ETX(a)
Definition: l_exception.h:67
bool is_finalized() const
Return whether the hasher is finalized, i.e., can I write to it?
Definition: wrap_openssl_evp.h:195
OpenSSL_EVP()
ctor must specify the algorithm
Definition: wrap_openssl_evp.h:114
Digest::const_iterator begin()
Return const iterator to start of message digest.
Definition: wrap_openssl_evp.h:181
size_t size() const
Return size of message digest.
Definition: wrap_openssl_evp.h:161
void put(const T &datum)
Hash a single primitive datum, using a "shallow read".
Definition: wrap_openssl_evp.h:143
Digest copy_digest()
Return a copy of the message digest.
Definition: wrap_openssl_evp.h:167
~OpenSSL_EVP()
this thing needs a dtor or it leaks
Definition: wrap_openssl_evp.h:123
#define KJB_THROW_2(ex, msg)
Definition: l_exception.h:48
#define ETX_2(a, msg)
Definition: l_exception.h:78
void write(const void *data, unsigned long len)
Hash an array of bytes; len is the number of bytes.
Definition: wrap_openssl_evp.h:135
std::vector< Unit > Digest
Type of output of the hasher.
Definition: wrap_openssl_evp.h:42
Support for error handling exception classes in libKJB.
Object thrown when a program lacks required resources or libraries.
Definition: l_exception.h:539
void write(SeqIterator begin, SeqIterator end)
Hash a container of primitive data via STL sequential iterators.
Definition: wrap_openssl_evp.h:150
Digest::const_iterator end()
Return const iterator to one-past-last of message digest.
Definition: wrap_openssl_evp.h:188
unsigned char Unit
The basic unit of both input and output for the hasher.
Definition: wrap_openssl_evp.h:39