2 //gcc openssl_evp.c pixmap_io.o -o openssl_evp -I /usr/include/openssl/ -lcrypto -O3 -std=c99
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>
12 #include "pixmap_io.h"
14 typedef unsigned char uchar;
25 struct timeval tstart;
26 gettimeofday(&tstart,0);
27 return( (double) (tstart.tv_sec + tstart.tv_usec*1e-6) );
30 double TimeStop(double t)
34 gettimeofday(&tend,0);
35 t = (double) (tend.tv_sec + tend.tv_usec*1e-6) - t;
40 void handleErrors(void)
42 ERR_print_errors_fp(stderr);
47 int encryptccm(unsigned char *plaintext, int plaintext_len, unsigned char *aad,
48 int aad_len, unsigned char *key, unsigned char *iv,
49 unsigned char *ciphertext, unsigned char *tag)
58 /* Create and initialise the context */
59 if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
61 /* Initialise the encryption operation. */
62 if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))
65 /* Setting IV len to 7. Not strictly necessary as this is the default
66 * but shown here for the purposes of this example */
67 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 7, NULL))
71 EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, NULL);
73 /* Initialise key and IV */
74 if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
76 /* Provide the total plaintext length
78 if(1 != EVP_EncryptUpdate(ctx, NULL, &len, NULL, plaintext_len))
81 /* Provide any AAD data. This can be called zero or one times as
84 if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
87 /* Provide the message to be encrypted, and obtain the encrypted output.
88 * EVP_EncryptUpdate can only be called once for this
90 if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
94 /* Finalise the encryption. Normally ciphertext bytes may be written at
95 * this stage, but this does not occur in CCM mode
97 if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
98 ciphertext_len += len;
101 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tag))
105 EVP_CIPHER_CTX_free(ctx);
107 return ciphertext_len;
111 int decryptccm(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad,
112 int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv,
113 unsigned char *plaintext)
120 /* Create and initialise the context */
121 if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
123 /* Initialise the decryption operation. */
124 if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL))
127 /* Setting IV len to 7. Not strictly necessary as this is the default
128 * but shown here for the purposes of this example */
129 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 7, NULL))
132 for(int i=0;i<16;i++) {
133 printf("%d ",tag[i]);
137 /* Set expected tag value. */
138 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, tag))
140 for(int i=0;i<16;i++) {
141 printf("%d ",tag[i]);
144 /* Initialise key and IV */
145 if(1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
148 /* Provide the total ciphertext length
150 if(1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_len))
153 /* Provide any AAD data. This can be called zero or more times as
156 if(1 != EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
159 /* Provide the message to be decrypted, and obtain the plaintext output.
160 * EVP_DecryptUpdate can be called multiple times if necessary
162 ret = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
164 printf("RET %d len %d\n",ret,len);
169 EVP_CIPHER_CTX_free(ctx);
174 return plaintext_len;
186 /* int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, */
187 /* unsigned char *iv, unsigned char *ciphertext, int ctr, int index) */
189 /* EVP_CIPHER_CTX *ctx; */
193 /* int ciphertext_len; */
195 /* /\* Create and initialise the context *\/ */
196 /* if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); */
198 /* /\* Initialise the encryption operation. IMPORTANT - ensure you use a key */
199 /* * and IV size appropriate for your cipher */
200 /* * In this example we are using 256 bit AES (i.e. a 256 bit key). The */
201 /* * IV size for *most* modes is the same as the block size. For AES this */
202 /* * is 128 bits *\/ */
203 /* //static double time=0; */
205 /* //t=TimeStart(); */
209 /* if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) */
210 /* handleErrors(); */
213 /* if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) */
214 /* handleErrors(); */
216 /* //time+=TimeStop(t); */
217 /* //printf("Time init %f\n",time); */
220 /* // int cipherBlockSize = EVP_CIPHER_CTX_block_size(ctx); */
221 /* // printf("INFO(evp_encrypt): block size: %d\n", cipherBlockSize); */
224 /* /\* Provide the message to be encrypted, and obtain the encrypted output. */
225 /* * EVP_EncryptUpdate can be called multiple times if necessary */
229 /* static double time=0; */
233 /* for(int i=0;i<nb_test;i++) */
236 /* if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) */
237 /* handleErrors(); */
238 /* ciphertext_len = len; */
241 /* /\* time+=TimeStop(t); */
242 /* // if(index==nb_test-1) */
243 /* printf("Time encrypt %f\n",time); */
248 /* /\* Finalise the encryption. Further ciphertext bytes may be written at */
251 /* if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); */
252 /* ciphertext_len += len; */
254 /* /\* Clean up *\/ */
255 /* EVP_CIPHER_CTX_free(ctx); */
257 /* return ciphertext_len; */
260 /* int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, */
261 /* unsigned char *iv, unsigned char *plaintext, int ctr, int index) */
263 /* EVP_CIPHER_CTX *ctx; */
267 /* int plaintext_len; */
269 /* /\* Create and initialise the context *\/ */
270 /* if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); */
272 /* /\* Initialise the decryption operation. IMPORTANT - ensure you use a key */
273 /* * and IV size appropriate for your cipher */
274 /* * In this example we are using 256 bit AES (i.e. a 256 bit key). The */
275 /* * IV size for *most* modes is the same as the block size. For AES this */
276 /* * is 128 bits *\/ */
282 /* if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) */
283 /* handleErrors(); */
286 /* if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) */
287 /* handleErrors(); */
289 /* /\* Provide the message to be decrypted, and obtain the plaintext output. */
290 /* * EVP_DecryptUpdate can be called multiple times if necessary */
293 /* /\* static double time=0; */
297 /* for(int i=0;i<nb_test;i++) */
299 /* plaintext_len = 0; */
300 /* if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) */
301 /* handleErrors(); */
302 /* plaintext_len = len; */
304 /* /\* time+=TimeStop(t); */
305 /* // if(index==nb_test-1) */
306 /* printf("Time decrypt %f\n",time); */
310 /* /\* Finalise the decryption. Further plaintext bytes may be written at */
313 /* if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors(); */
314 /* plaintext_len += len; */
318 /* /\* Clean up *\/ */
319 /* EVP_CIPHER_CTX_free(ctx); */
321 /* return plaintext_len; */
327 int main (int argc, char** argv)
329 /* Set up the key and iv. Do I need to say to not hard code these in a
330 * real application? :-)
337 for(int i=1; i<argc; i++){
338 if(strncmp(argv[i],"nb",2)==0) nb_test = atoi(&(argv[i][2])); //nb of test
339 if(strncmp(argv[i],"ctr",3)==0) ctr = atoi(&(argv[i][3])); //CTR ? 1 otherwise CBC like
340 if(strncmp(argv[i],"sizebuf",7)==0) size_buf = atoi(&(argv[i][7])); //SIZE of the buffer
341 if(strncmp(argv[i],"lena",4)==0) lena = atoi(&(argv[i][4])); //Use Lena or buffer
344 /* printf("nb times %d\n",nb_test);
345 printf("ctr %d\n",ctr);
346 printf("lena %d\n",lena);
347 printf("size_buf %d\n",size_buf);
354 // unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
355 unsigned char *key = (unsigned char *)"01234567890123450123456789012345";
358 unsigned char *iv = (unsigned char *)"0123456789012345";
360 unsigned char *tag= malloc(16);
362 /* Message to be encrypted */
364 /* Buffer for ciphertext. Ensure the buffer is long enough for the
365 * ciphertext which may be longer than the plaintext, dependant on the
371 uchar *data_R, *data_G, *data_B;
377 load_RGB_pixmap("lena.ppm", &width, &height, &data_R, &data_G, &data_B);
378 imsize=width*height*3;
379 // load_RGB_pixmap("No_ecb_mode_picture.ppm", &width, &height, &data_R, &data_G, &data_B);
385 buffer=malloc(imsize*sizeof(uchar));
386 for(int i=0;i<imsize;i++) {
393 int oneD=width*height;
394 uchar *plaintext = malloc(imsize+1000); //add that for cbc
396 for(int i=0;i<oneD;i++) {
397 plaintext[i]=data_R[i];
398 plaintext[oneD+i]=data_G[i];
399 plaintext[2*oneD+i]=data_B[i];
404 for(int i=0;i<oneD;i++) {
405 plaintext[i]=buffer[i];
411 uchar *ciphertext = malloc(imsize+1000); //add that for cbc
413 /* Buffer for the decrypted text */
414 uchar *decryptedtext = malloc(imsize+1000); //add that for cbc
416 int decryptedtext_len, ciphertext_len;
418 /* Initialise the library */
419 /* ERR_load_crypto_strings();
420 OpenSSL_add_all_algorithms();
421 OPENSSL_config(NULL);
425 double time_encrypt=0;
426 double time_decrypt=0;
427 double t=TimeStart();
430 /* Encrypt the plaintext */
437 for(int i=0;i<16;i++)
438 printf("%d ",tag[i]);
441 // for(i=0;i<nb_test;i++)
443 ciphertext_len = encryptccm (plaintext, imsize, plaintext, imsize, key, iv,
446 for(int i=0;i<16;i++) {
447 printf("%d ",tag[i]);
450 time_encrypt+=TimeStop(t);
452 // printf("Time encrypt %f\n",time);
453 printf("%f\t",(double)imsize*nb_test/time_encrypt);
456 for(int i=0;i<oneD;i++) {
457 data_R[i]=ciphertext[i];
458 data_G[i]=ciphertext[oneD+i];
459 data_B[i]=ciphertext[2*oneD+i];
461 store_RGB_pixmap("lena2.ppm", data_R, data_G, data_B, width, height);
470 //for(int i=0;i<nb_test;i++)
472 /* Decrypt the ciphertext */
473 decryptedtext_len = decryptccm(ciphertext, ciphertext_len,ciphertext, ciphertext_len,tag, key, iv,
477 time_decrypt+=TimeStop(t);
479 //printf("Time decrypt %f\n",time);
480 printf("%f\t",(double)imsize*nb_test/time_decrypt);
483 for(int i=0;i<oneD;i++) {
484 data_R[i]=decryptedtext[i];
485 data_G[i]=decryptedtext[oneD+i];
486 data_B[i]=decryptedtext[2*oneD+i];
488 store_RGB_pixmap("lena3.ppm", data_R, data_G, data_B, width, height);
492 for(int i=0;i<imsize;i++) {
493 //cout<<(int)buffer[i]<<endl;
494 if(buffer[i]!=decryptedtext[i]) {
498 // printf("RESULT CORRECT: %d\n",equal);