Diana Software
QCryptoRSAEnvelope.cc
Go to the documentation of this file.
1 #include "QCryptoRSAEnvelope.hh"
2 #include "QDiana.hh"
3 #include "QError.hh"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sstream>
7 
8 #include <openssl/pem.h>
9 #include <openssl/rsa.h>
10 #include <openssl/evp.h>
11 #include <openssl/err.h>
12 
13 #include <arpa/inet.h> /* For htonl() */
14 
16 
17 
18 
19 QCryptoRSAEnvelope::QCryptoRSAEnvelope(const std::string& pKey, const QCryptoRSAEnvelope::Mode mode)
20 {
21  fCTX = NULL;
22  RSA *rsa_pkey = NULL;
23  fPKey = NULL;
24  FILE* inputKeyFile = fopen(pKey.c_str(),"r");
25  fMode = mode;
26  if(!inputKeyFile) {
28  std::stringstream msg;
29  msg<<"Cannot open file: "<<pKey;
30  err.SetDescription(__FILE__,__LINE__,msg.str());
31  DianaThrow(err);
32  }
33 
34  if(mode == ENCRYPT) {
35  if (!PEM_read_RSA_PUBKEY(inputKeyFile, &rsa_pkey, NULL, NULL)) {
37  err.SetDescription(__FILE__,__LINE__,"Error loading RSA Public Key File");
38  DianaThrow(err);
39  }
40  } else if(mode == DECRYPT) {
41  if (!PEM_read_RSAPrivateKey(inputKeyFile, &rsa_pkey, NULL, NULL)) {
43  err.SetDescription(__FILE__,__LINE__,"Error loading RSA Private Key File");
44  DianaThrow(err);
45  }
46  } else {
48  err.SetDescription(__FILE__,__LINE__,"Mode must be encrypt or decrypt");
49  DianaThrow(err);
50  }
51  if(inputKeyFile) fclose(inputKeyFile);
52 
53  fPKey = EVP_PKEY_new();
54  if (!EVP_PKEY_assign_RSA(fPKey, rsa_pkey)) {
56  err.SetDescription("__FILE__,__LINE__,EVP_PKEY_assign_RSA: failed.");
57  DianaThrow(err);
58  }
59 
60  fCTX = EVP_CIPHER_CTX_new();
61  EVP_CIPHER_CTX_init(fCTX);
62 }
63 
64 
65 
67 {
68  if(fPKey) EVP_PKEY_free(fPKey);
69  if(fCTX != NULL)
70  EVP_CIPHER_CTX_free(fCTX);
71 }
72 
73 
74 
75 std::vector<unsigned char> QCryptoRSAEnvelope::Process(const std::string& message)
76 {
77  if(fMode != ENCRYPT) {
79  err.SetDescription("__FILE__,__LINE__,string message allowed only when encrypting");
80  DianaThrow(err);
81  }
82  std::vector<unsigned char> output(message.size());
83  for(size_t i = 0; i < message.size(); i++) {
84  output[i] = message[i];
85  }
86  return Process(output);
87 }
88 
89 std::vector<unsigned char> QCryptoRSAEnvelope::Process(const std::vector<unsigned char>& message)
90 {
91  int eklen;
92  size_t totLength;
93  int len_out;
94 
95  unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH*2];
96  if(fMode == ENCRYPT) {
97  totLength = EVP_CIPHER_iv_length(EVP_aes_128_cbc());
98  std::cout<<"IV:length: "<<totLength<<std::endl;
99 
100  unsigned char* ek = (unsigned char*) malloc(4096);
101  // init and write iv to buffer_out
102  if (!EVP_SealInit(fCTX, EVP_aes_128_cbc(), &ek, &eklen, buffer_out, &fPKey, 1)) {
104  err.SetDescription(__FILE__,__LINE__,"EVP_SealInit: failed.");
105  DianaThrow(err);
106  }
107 
108 // Print("E:IV:",buffer_out,totLength);
109  if(eklen < 0 ) eklen = 0;
110  std::cout<<"E:length: "<<eklen<<std::endl;
111  //Print("E:EK:",ek,eklen);
112 
113  // write ek and eklen to buffer_out
114  uint32_t eklen_n = htonl(eklen);
115  memcpy(buffer_out+totLength, &eklen_n,sizeof(eklen_n));
116 
117  totLength += sizeof(eklen_n);
118  memcpy(buffer_out+totLength,ek,eklen);
119  totLength += eklen;
120  free(ek);
121 
122  // write encrypted message
123  unsigned char* buffer_in = Convert(message);
124  size_t n = message.size();
125 
126  if (!EVP_SealUpdate(fCTX, buffer_out+totLength, &len_out, buffer_in, n )) {
127 
129  err.SetDescription(__FILE__,__LINE__,"EVP_SealUpdate: failed.");
130  DianaThrow(err);
131  }
132  free(buffer_in);
133  totLength += len_out;
134 
135  if (!EVP_SealFinal(fCTX, buffer_out+totLength, &len_out))
136  {
138  err.SetDescription(__FILE__,__LINE__,"EVP_SealFinal: failed.");
139  DianaThrow(err);
140  }
141  totLength += len_out;
142 
143  } else {
144 
145  unsigned char* buffer_in = Convert(message);
146  size_t n = message.size();
147  totLength = EVP_CIPHER_iv_length(EVP_aes_128_cbc());
148  unsigned char* iv = buffer_in;
149  //Print("D:IV:",iv,totLength);
150 
151  // read eklen and ek
152  uint32_t eklen_n;
153  memcpy(&eklen_n,buffer_in+totLength,sizeof(eklen_n));
154  totLength += sizeof(eklen_n);
155  eklen = ntohl(eklen_n);
156  unsigned char* ek = buffer_in+totLength;
157  totLength += eklen;
158 
159  //std::cout<<"D:length: "<<eklen<<std::endl;
160  //Print("D:EK:",ek,eklen);
161 
162 
163  if (!EVP_OpenInit(fCTX, EVP_aes_128_cbc(), ek, eklen, iv, fPKey))
164  {
166  err.SetDescription(__FILE__,__LINE__,"EVP_OpenInit: failed.");
167  DianaThrow(err);
168  }
169 
170  len_out = 0;
171 
172  if (!EVP_OpenUpdate(fCTX, buffer_out, &len_out, buffer_in+totLength, n-totLength))
173  {
175  err.SetDescription(__FILE__,__LINE__,"EVP_OpenUpdate: failed.");
176  DianaThrow(err);
177 
178  }
179  totLength = len_out;
180  if (!EVP_OpenFinal(fCTX, buffer_out+len_out, &len_out))
181  {
183  err.SetDescription(__FILE__,__LINE__,"EVP_OpenFinal: failed.");
184  DianaThrow(err);
185  }
186  totLength += len_out;
187  free(buffer_in);
188  }
189 
190  return Convert(buffer_out,totLength);
191 
192 }
193 
194 unsigned char* QCryptoRSAEnvelope::Convert(const std::vector<unsigned char>& input)
195 {
196  unsigned char* output = (unsigned char*) malloc(sizeof(char)*input.size());
197  for(size_t i = 0; i < input.size(); i++) {
198  output[i] = input[i];
199  }
200  return output;
201 }
202 
203 std::vector<unsigned char> QCryptoRSAEnvelope::Convert(const unsigned char* input, const size_t n)
204 {
205  std::vector<unsigned char> output(n);
206  for(size_t i = 0; i < n; i++) {
207  output[i] = input[i];
208  }
209  return output;
210 }
211 
212 
213 void QCryptoRSAEnvelope::Print(const char* header, const unsigned char* data, const size_t n)
214 {
215  printf("%s: ",header);
216  for(size_t c = 0; c < n; c++) printf("%x",data[c]);
217  printf("\n");
218 
219 
220 }
221 
222 
err
Definition: CheckOF.C:114
ClassImp(QCryptoRSAEnvelope) QCryptoRSAEnvelope
struct rsa_st RSA
Definition: QCryptoRSA.hh:7
#define DianaThrow(obj)
Definition: QDianaDebug.hh:26
@ QERR_UNKNOWN_ERR
Definition: QError.hh:108
@ QERR_CANNOT_OPEN_FILE
Definition: QError.hh:33
QCryptoRSAEnvelope(const std::string &pKey, const Mode mode)
std::vector< unsigned char > Process(const std::vector< unsigned char > &message)
EVP_CIPHER_CTX * fCTX
void Print(const char *header, const unsigned char *data, const size_t n)
unsigned char * Convert(const std::vector< unsigned char > &input)
error class with error type and description
Definition: QError.hh:115