IBR-DTNSuite  0.10
RSASHA256Stream.cpp
Go to the documentation of this file.
1 /*
2  * RSASHA256Stream.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/err.h>
25 
26 namespace ibrcommon
27 {
28  RSASHA256Stream::RSASHA256Stream(EVP_PKEY * const pkey, bool verify)
29  : ostream(this), out_buf_(BUFF_SIZE), _pkey(pkey), _verify(verify), _sign_valid(false), _return_code(0)
30  {
31  // Initialize get pointer. This should be zero so that underflow is called upon first read.
32  setp(&out_buf_[0], &out_buf_[BUFF_SIZE - 1]);
33  EVP_MD_CTX_init(&_ctx);
34 
35  if (!_verify)
36  {
37  if (!EVP_SignInit_ex(&_ctx, EVP_sha256(), NULL))
38  {
39  IBRCOMMON_LOGGER_TAG("RSASHA256Stream", critical) << "failed to initialize the signature function" << IBRCOMMON_LOGGER_ENDL;
40  ERR_print_errors_fp(stderr);
41  }
42  }
43  else
44  {
45  if (!EVP_VerifyInit_ex(&_ctx, EVP_sha256(), NULL))
46  {
47  IBRCOMMON_LOGGER_TAG("RSASHA256Stream", critical) << "failed to initialize the verification function" << IBRCOMMON_LOGGER_ENDL;
48  ERR_print_errors_fp(stderr);
49  }
50  }
51  }
52 
54  {
55  EVP_MD_CTX_cleanup(&_ctx);
56  }
57 
59  {
60  EVP_MD_CTX_cleanup(&_ctx);
61 
62  EVP_MD_CTX_init(&_ctx);
63 
64  if (!_verify)
65  {
66  if (!EVP_SignInit_ex(&_ctx, EVP_sha256(), NULL))
67  {
68  IBRCOMMON_LOGGER_TAG("RSASHA256Stream", critical) << "failed to initialize the signature function" << IBRCOMMON_LOGGER_ENDL;
69  ERR_print_errors_fp(stderr);
70  }
71  }
72  else
73  {
74  if (!EVP_VerifyInit_ex(&_ctx, EVP_sha256(), NULL))
75  {
76  IBRCOMMON_LOGGER_TAG("RSASHA256Stream", critical) << "failed to initialize the verfication function" << IBRCOMMON_LOGGER_ENDL;
77  ERR_print_errors_fp(stderr);
78  }
79  }
80 
81  _sign_valid = false;
82  }
83 
84  const std::pair< const int, const std::string > RSASHA256Stream::getSign()
85  {
86  // check if data was feed into the stream and the sign needs to be
87  // recalculated
88  if (!_sign_valid)
89  {
90  sync();
91  std::vector<unsigned char> sign(EVP_PKEY_size(_pkey));
92  unsigned int size = EVP_PKEY_size(_pkey);
93 
94  _return_code = EVP_SignFinal(&_ctx, &sign[0], &size, _pkey);
95 
96  _sign = std::string((const char*)&sign[0], size);
97 
98  _sign_valid = true;
99  }
100  return std::pair<const int, const std::string>(_return_code, _sign);
101  }
102 
103  int RSASHA256Stream::getVerification(const std::string& their_sign)
104  {
105  // check if data was feed into the stream and the sign needs to be
106  // recalculated
107  if (!_sign_valid)
108  {
109  sync();
110  _return_code = EVP_VerifyFinal(&_ctx, reinterpret_cast<const unsigned char *>(their_sign.c_str()), static_cast<unsigned int>(their_sign.size()), _pkey);
111  _sign_valid = true;
112  }
113  return _return_code;
114  }
115 
117  {
118  int ret = std::char_traits<char>::eq_int_type(this->overflow(
119  std::char_traits<char>::eof()), std::char_traits<char>::eof()) ? -1
120  : 0;
121 
122  return ret;
123  }
124 
125  RSASHA256Stream::traits::int_type RSASHA256Stream::overflow(RSASHA256Stream::traits::int_type c)
126  {
127  char *ibegin = &out_buf_[0];
128  char *iend = pptr();
129 
130  // mark the buffer as free
131  setp(&out_buf_[0], &out_buf_[BUFF_SIZE - 1]);
132 
133  if (!std::char_traits<char>::eq_int_type(c, std::char_traits<char>::eof()))
134  {
135  //TODO writing one byte after the buffer?
136  *iend++ = std::char_traits<char>::to_char_type(c);
137  }
138 
139  // if there is nothing to send, just return
140  if ((iend - ibegin) == 0)
141  {
142  return std::char_traits<char>::not_eof(c);
143  }
144 
145  if (!_verify)
146  // hashing
147  {
148  if (!EVP_SignUpdate(&_ctx, &out_buf_[0], iend - ibegin))
149  {
150  IBRCOMMON_LOGGER_TAG("RSASHA256Stream", critical) << "failed to feed data into the signature function" << IBRCOMMON_LOGGER_ENDL;
151  ERR_print_errors_fp(stderr);
152  }
153  }
154  else
155  {
156  if (!EVP_VerifyUpdate(&_ctx, &out_buf_[0], iend - ibegin))
157  {
158  IBRCOMMON_LOGGER_TAG("RSASHA256Stream", critical) << "failed to feed data into the verification function" << IBRCOMMON_LOGGER_ENDL;
159  ERR_print_errors_fp(stderr);
160  }
161  }
162 
163  return std::char_traits<char>::not_eof(c);
164  }
165 }