]> AND Private Git Repository - Cipher_code.git/blob - OneRoundIoT/openssl/openssl_evp_gcm.c
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
yes
[Cipher_code.git] / OneRoundIoT / openssl / openssl_evp_gcm.c
1 //gcc pixmap_io.c  -c
2 //gcc openssl_evp.c pixmap_io.o -o  openssl_evp -I /usr/include/openssl/ -lcrypto -O3 -std=c99 
3
4
5 #include <openssl/conf.h>
6 #include <openssl/evp.h>
7 #include <openssl/err.h>
8 #include <openssl/ssl.h>
9 #include <openssl/bio.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include "pixmap_io.h"
13
14 typedef unsigned char   uchar;
15
16 int nb_test=1;
17 int ctr=0;
18
19
20
21
22
23 double TimeStart()
24 {
25   struct timeval tstart;
26   gettimeofday(&tstart,0);
27   return( (double) (tstart.tv_sec + tstart.tv_usec*1e-6) );
28 }
29
30 double TimeStop(double t)
31 {
32   struct timeval tend;
33
34   gettimeofday(&tend,0);
35   t = (double) (tend.tv_sec + tend.tv_usec*1e-6) - t;
36   return (t);
37 }
38
39
40 void handleErrors(void)
41 {
42   ERR_print_errors_fp(stderr);
43   abort();
44 }
45
46 int encryptgcm(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
47         int aad_len, unsigned char *key, unsigned char *iv, int iv_len,
48         unsigned char *ciphertext, unsigned char *tag)
49 {
50         EVP_CIPHER_CTX *ctx;
51
52         int len;
53
54         int ciphertext_len;
55
56
57         /* Create and initialise the context */
58         if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
59
60         /* Initialise the encryption operation. */
61         if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
62                 handleErrors();
63
64         /* Set IV length if default 12 bytes (96 bits) is not appropriate */
65         if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
66                 handleErrors();
67         for(int i=0;i<nb_test;i++) {
68           /* Initialise key and IV */
69           if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
70           
71           /* Provide any AAD data. This can be called zero or more times as
72            * required
73            */
74           
75           
76           if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
77             handleErrors();
78           
79           /* Provide the message to be encrypted, and obtain the encrypted output.
80            * EVP_EncryptUpdate can be called multiple times if necessary
81            */
82           
83           
84           if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
85             handleErrors();
86           ciphertext_len = len;
87           
88           
89           /* Finalise the encryption. Normally ciphertext bytes may be written at
90            * this stage, but this does not occur in GCM mode
91            */
92           if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
93           ciphertext_len += len;
94           
95           /* Get the tag */
96           if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
97             handleErrors();
98         }
99         /* Clean up */
100         EVP_CIPHER_CTX_free(ctx);
101
102         return ciphertext_len;
103 }
104
105
106
107
108 int decryptgcm(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
109         int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
110         int iv_len, unsigned char *plaintext)
111 {
112         EVP_CIPHER_CTX *ctx;
113         int len;
114         int plaintext_len;
115         int ret;
116
117         /* Create and initialise the context */
118         if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
119
120         /* Initialise the decryption operation. */
121         if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
122                 handleErrors();
123
124         /* Set IV length. Not necessary if this is 12 bytes (96 bits) */
125         if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL))
126                 handleErrors();
127         for(int i=0;i<nb_test;i++) {
128           /* Initialise key and IV */
129           if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
130           
131           /* Provide any AAD data. This can be called zero or more times as
132            * required
133            */
134           if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
135             handleErrors();
136           
137           /* Provide the message to be decrypted, and obtain the plaintext output.
138            * EVP_DecryptUpdate can be called multiple times if necessary
139            */
140           if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
141             handleErrors();
142           plaintext_len = len;
143           
144           /* Set expected tag value. Works in OpenSSL 1.0.1d and later */
145           if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag))
146             handleErrors();
147           
148           /* Finalise the decryption. A positive return value indicates success,
149            * anything else is a failure - the plaintext is not trustworthy.
150            */
151           ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len);
152         }
153
154           
155         /* Clean up */
156         EVP_CIPHER_CTX_free(ctx);
157
158         if(ret > 0)
159         {
160                 /* Success */
161                 plaintext_len += len;
162                 return plaintext_len;
163         }
164         else
165         {
166                 /* Verify failed */
167                 return -1;
168         }
169 }
170
171 /* int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, */
172 /*          unsigned char *iv, unsigned char *ciphertext, int ctr, int index) */
173 /* { */
174 /*   EVP_CIPHER_CTX *ctx; */
175
176 /*   int len; */
177
178 /*   int ciphertext_len; */
179
180 /*   /\* Create and initialise the context *\/ */
181 /*   if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); */
182
183 /*   /\* Initialise the encryption operation. IMPORTANT - ensure you use a key */
184 /*    * and IV size appropriate for your cipher */
185 /*    * In this example we are using 256 bit AES (i.e. a 256 bit key). The */
186 /*    * IV size for *most* modes is the same as the block size. For AES this */
187 /*    * is 128 bits *\/ */
188 /*   //static double  time=0; */
189 /*   //double t=0; */
190 /*   //t=TimeStart(); */
191 /*   //256 */
192 /*   //avant ecb */
193 /*   if(ctr) { */
194 /*     if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) */
195 /*       handleErrors(); */
196 /*   } */
197 /*   else */
198 /*       if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) */
199 /*      handleErrors(); */
200
201 /*   //time+=TimeStop(t); */
202 /*   //printf("Time init %f\n",time); */
203
204   
205 /* //  int cipherBlockSize = EVP_CIPHER_CTX_block_size(ctx);   */
206 /* //  printf("INFO(evp_encrypt): block size: %d\n", cipherBlockSize); */
207
208   
209 /*   /\* Provide the message to be encrypted, and obtain the encrypted output. */
210 /*    * EVP_EncryptUpdate can be called multiple times if necessary */
211 /*    *\/ */
212
213 /* /\* */
214 /*   static double  time=0; */
215 /*   double t=0; */
216 /*   t=TimeStart(); */
217 /* *\/ */
218 /*   for(int i=0;i<nb_test;i++) */
219 /*   {   */
220   
221 /*       if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) */
222 /*       handleErrors(); */
223 /*     ciphertext_len = len; */
224     
225 /*   } */
226 /* /\*  time+=TimeStop(t); */
227 /*   // if(index==nb_test-1) */
228 /*   printf("Time encrypt %f\n",time); */
229     
230 /* *\/ */
231
232   
233 /*   /\* Finalise the encryption. Further ciphertext bytes may be written at */
234 /*    * this stage. */
235 /*    *\/ */
236 /*   if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); */
237 /*   ciphertext_len += len; */
238
239 /*   /\* Clean up *\/ */
240 /*   EVP_CIPHER_CTX_free(ctx); */
241
242 /*   return ciphertext_len; */
243 /* } */
244
245 /* int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, */
246 /*          unsigned char *iv, unsigned char *plaintext, int ctr, int index) */
247 /* { */
248 /*   EVP_CIPHER_CTX *ctx; */
249
250 /*   int len; */
251
252 /*   int plaintext_len; */
253
254 /*   /\* Create and initialise the context *\/ */
255 /*   if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); */
256
257 /*   /\* Initialise the decryption operation. IMPORTANT - ensure you use a key */
258 /*    * and IV size appropriate for your cipher */
259 /*    * In this example we are using 256 bit AES (i.e. a 256 bit key). The */
260 /*    * IV size for *most* modes is the same as the block size. For AES this */
261 /*    * is 128 bits *\/ */
262
263 /*   //256 */
264
265 /*   //avant => ecb */
266 /*   if(ctr) { */
267 /*     if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) */
268 /*       handleErrors(); */
269 /*   } */
270 /*   else */
271 /*       if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) */
272 /*     handleErrors(); */
273
274 /*   /\* Provide the message to be decrypted, and obtain the plaintext output. */
275 /*    * EVP_DecryptUpdate can be called multiple times if necessary */
276 /*    *\/ */
277   
278 /* /\*  static double time=0; */
279 /*   double t=0; */
280 /*   t=TimeStart(); */
281 /* *\/ */
282 /*   for(int i=0;i<nb_test;i++) */
283 /*   {   */
284 /*     plaintext_len = 0; */
285 /*     if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) */
286 /*       handleErrors(); */
287 /*     plaintext_len = len; */
288 /*   } */
289 /* /\*  time+=TimeStop(t); */
290 /* //  if(index==nb_test-1) */
291 /*     printf("Time decrypt %f\n",time); */
292 /* *\/ */
293
294   
295 /*   /\* Finalise the decryption. Further plaintext bytes may be written at */
296 /*    * this stage. */
297 /*    *\/ */
298 /*   if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors(); */
299 /*   plaintext_len += len; */
300
301   
302   
303 /*   /\* Clean up *\/ */
304 /*   EVP_CIPHER_CTX_free(ctx); */
305
306 /*   return plaintext_len; */
307 /* } */
308
309
310
311
312 int main (int argc, char** argv)
313 {
314   /* Set up the key and iv. Do I need to say to not hard code these in a
315    * real application? :-)
316    */
317
318   int size_buf=1;
319   int lena=0;
320
321    
322   for(int i=1; i<argc; i++){
323     if(strncmp(argv[i],"nb",2)==0)    nb_test = atoi(&(argv[i][2]));    //nb of test         
324     if(strncmp(argv[i],"ctr",3)==0) ctr = atoi(&(argv[i][3]));          //CTR ? 1  otherwise CBC like
325     if(strncmp(argv[i],"sizebuf",7)==0) size_buf = atoi(&(argv[i][7]));          //SIZE of the buffer
326     if(strncmp(argv[i],"lena",4)==0) lena = atoi(&(argv[i][4]));          //Use Lena or buffer
327   }
328
329 /*  printf("nb times %d\n",nb_test);
330   printf("ctr %d\n",ctr);
331   printf("lena %d\n",lena);
332   printf("size_buf %d\n",size_buf);
333 */
334
335
336
337   
338   /* A 256 bit key */
339 //  unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
340   unsigned char *key = (unsigned char *)"01234567890123450123456789012345";
341   
342   /* A 128 bit IV */
343   unsigned char *iv = (unsigned char *)"0123456789012345";
344
345   unsigned char *tag=  malloc(16);
346   
347   /* Message to be encrypted */
348
349   /* Buffer for ciphertext. Ensure the buffer is long enough for the
350    * ciphertext which may be longer than the plaintext, dependant on the
351    * algorithm and mode
352    */
353
354   int width;
355   int height;
356   uchar *data_R, *data_G, *data_B;
357   int imsize;
358   uchar *buffer;
359
360
361   if(lena==1) {
362     load_RGB_pixmap("lena.ppm", &width, &height, &data_R, &data_G, &data_B);
363     imsize=width*height*3;
364 //  load_RGB_pixmap("No_ecb_mode_picture.ppm", &width, &height, &data_R, &data_G, &data_B);
365   }
366   else {
367     width=size_buf;
368     height=size_buf;
369     imsize=width*height;
370     buffer=malloc(imsize*sizeof(uchar));
371     for(int i=0;i<imsize;i++) {
372       buffer[i]=lrand48();
373     }
374   }
375   
376
377
378   int oneD=width*height;
379   uchar *plaintext = malloc(imsize+1000);   //add that for cbc
380   if(lena) {
381     for(int i=0;i<oneD;i++) {
382       plaintext[i]=data_R[i];
383       plaintext[oneD+i]=data_G[i];
384       plaintext[2*oneD+i]=data_B[i];
385     }
386   }
387   else
388   {
389      for(int i=0;i<oneD;i++) {
390        plaintext[i]=buffer[i];
391     }
392   }
393
394   
395
396   uchar *ciphertext = malloc(imsize+1000); //add that for cbc
397
398   /* Buffer for the decrypted text */
399   uchar *decryptedtext = malloc(imsize+1000); //add that for cbc
400
401   int decryptedtext_len, ciphertext_len;
402
403   /* Initialise the library */
404 /*  ERR_load_crypto_strings();
405   OpenSSL_add_all_algorithms();
406   OPENSSL_config(NULL);
407 */
408
409
410   double time_encrypt=0;
411   double time_decrypt=0;
412   double t=TimeStart();
413
414   
415   /* Encrypt the plaintext */
416
417
418   int i;
419
420
421
422 /*  for(int i=0;i<16;i++)
423     printf("%d ",tag[i]);
424   printf("\n");
425 */
426 //  for(i=0;i<nb_test;i++)
427   {  
428     ciphertext_len = encryptgcm (plaintext, imsize, plaintext, imsize, key, iv,16,
429                               ciphertext, tag);
430   }
431 /*  for(int i=0;i<16;i++) {
432     printf("%d ",tag[i]);
433   }
434   printf("\n");*/
435  time_encrypt+=TimeStop(t);
436
437 // printf("Time encrypt %f\n",time);
438  printf("%f\t",(double)imsize*nb_test/time_encrypt);
439
440  if(lena) {
441    for(int i=0;i<oneD;i++) {
442      data_R[i]=ciphertext[i];
443      data_G[i]=ciphertext[oneD+i];
444      data_B[i]=ciphertext[2*oneD+i];
445    }
446    store_RGB_pixmap("lena2.ppm", data_R, data_G, data_B, width, height);
447  }
448  
449   
450   t=0;
451   t=TimeStart();
452
453
454   
455 //  for(int i=0;i<nb_test;i++)
456   {  
457     /* Decrypt the ciphertext */
458     decryptedtext_len = decryptgcm(ciphertext, ciphertext_len,ciphertext, ciphertext_len,tag,  key, iv, 16,
459                                 decryptedtext);
460   }
461
462  time_decrypt+=TimeStop(t);
463
464  //printf("Time decrypt %f\n",time);
465  printf("%f\t",(double)imsize*nb_test/time_decrypt);
466
467  if(lena) {
468    for(int i=0;i<oneD;i++) {
469      data_R[i]=decryptedtext[i];
470      data_G[i]=decryptedtext[oneD+i];
471      data_B[i]=decryptedtext[2*oneD+i];
472    }
473    store_RGB_pixmap("lena3.ppm", data_R, data_G, data_B, width, height);
474  }
475  else {
476    int equal=1;
477    for(int i=0;i<imsize;i++) {
478      //cout<<(int)buffer[i]<<endl;
479      if(buffer[i]!=decryptedtext[i]) {
480        equal=0;
481      }
482    }
483 //   printf("RESULT CORRECT: %d\n",equal);
484  }
485   
486
487   /* Clean up */
488   EVP_cleanup();
489   ERR_free_strings();
490
491   return 0;
492 }