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_chacha20_poly1305(), 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_chacha20_poly1305(), 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 /* Set expected tag value. */
133 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, tag))
136 /* Initialise key and IV */
137 if(1 != EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors();
140 /* Provide the total ciphertext length
142 if(1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_len))
145 /* Provide any AAD data. This can be called zero or more times as
148 if(1 != EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
151 /* Provide the message to be decrypted, and obtain the plaintext output.
152 * EVP_DecryptUpdate can be called multiple times if necessary
154 ret = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len);
156 // printf("RET %d len %d\n",ret,len);
161 EVP_CIPHER_CTX_free(ctx);
166 return plaintext_len;
178 /* int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, */
179 /* unsigned char *iv, unsigned char *ciphertext, int ctr, int index) */
181 /* EVP_CIPHER_CTX *ctx; */
185 /* int ciphertext_len; */
187 /* /\* Create and initialise the context *\/ */
188 /* if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); */
190 /* /\* Initialise the encryption operation. IMPORTANT - ensure you use a key */
191 /* * and IV size appropriate for your cipher */
192 /* * In this example we are using 256 bit AES (i.e. a 256 bit key). The */
193 /* * IV size for *most* modes is the same as the block size. For AES this */
194 /* * is 128 bits *\/ */
195 /* //static double time=0; */
197 /* //t=TimeStart(); */
201 /* if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) */
202 /* handleErrors(); */
205 /* if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) */
206 /* handleErrors(); */
208 /* //time+=TimeStop(t); */
209 /* //printf("Time init %f\n",time); */
212 /* // int cipherBlockSize = EVP_CIPHER_CTX_block_size(ctx); */
213 /* // printf("INFO(evp_encrypt): block size: %d\n", cipherBlockSize); */
216 /* /\* Provide the message to be encrypted, and obtain the encrypted output. */
217 /* * EVP_EncryptUpdate can be called multiple times if necessary */
221 /* static double time=0; */
225 /* for(int i=0;i<nb_test;i++) */
228 /* if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) */
229 /* handleErrors(); */
230 /* ciphertext_len = len; */
233 /* /\* time+=TimeStop(t); */
234 /* // if(index==nb_test-1) */
235 /* printf("Time encrypt %f\n",time); */
240 /* /\* Finalise the encryption. Further ciphertext bytes may be written at */
243 /* if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); */
244 /* ciphertext_len += len; */
246 /* /\* Clean up *\/ */
247 /* EVP_CIPHER_CTX_free(ctx); */
249 /* return ciphertext_len; */
252 /* int decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, */
253 /* unsigned char *iv, unsigned char *plaintext, int ctr, int index) */
255 /* EVP_CIPHER_CTX *ctx; */
259 /* int plaintext_len; */
261 /* /\* Create and initialise the context *\/ */
262 /* if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); */
264 /* /\* Initialise the decryption operation. IMPORTANT - ensure you use a key */
265 /* * and IV size appropriate for your cipher */
266 /* * In this example we are using 256 bit AES (i.e. a 256 bit key). The */
267 /* * IV size for *most* modes is the same as the block size. For AES this */
268 /* * is 128 bits *\/ */
274 /* if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv)) */
275 /* handleErrors(); */
278 /* if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv)) */
279 /* handleErrors(); */
281 /* /\* Provide the message to be decrypted, and obtain the plaintext output. */
282 /* * EVP_DecryptUpdate can be called multiple times if necessary */
285 /* /\* static double time=0; */
289 /* for(int i=0;i<nb_test;i++) */
291 /* plaintext_len = 0; */
292 /* if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) */
293 /* handleErrors(); */
294 /* plaintext_len = len; */
296 /* /\* time+=TimeStop(t); */
297 /* // if(index==nb_test-1) */
298 /* printf("Time decrypt %f\n",time); */
302 /* /\* Finalise the decryption. Further plaintext bytes may be written at */
305 /* if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) handleErrors(); */
306 /* plaintext_len += len; */
310 /* /\* Clean up *\/ */
311 /* EVP_CIPHER_CTX_free(ctx); */
313 /* return plaintext_len; */
319 int main (int argc, char** argv)
321 /* Set up the key and iv. Do I need to say to not hard code these in a
322 * real application? :-)
329 for(int i=1; i<argc; i++){
330 if(strncmp(argv[i],"nb",2)==0) nb_test = atoi(&(argv[i][2])); //nb of test
331 if(strncmp(argv[i],"ctr",3)==0) ctr = atoi(&(argv[i][3])); //CTR ? 1 otherwise CBC like
332 if(strncmp(argv[i],"sizebuf",7)==0) size_buf = atoi(&(argv[i][7])); //SIZE of the buffer
333 if(strncmp(argv[i],"lena",4)==0) lena = atoi(&(argv[i][4])); //Use Lena or buffer
336 /* printf("nb times %d\n",nb_test);
337 printf("ctr %d\n",ctr);
338 printf("lena %d\n",lena);
339 printf("size_buf %d\n",size_buf);
346 // unsigned char *key = (unsigned char *)"01234567890123456789012345678901";
347 unsigned char *key = (unsigned char *)"01234567890123450123456789012345";
350 unsigned char *iv = (unsigned char *)"0123456789012345";
352 unsigned char *tag= malloc(16);
354 /* Message to be encrypted */
356 /* Buffer for ciphertext. Ensure the buffer is long enough for the
357 * ciphertext which may be longer than the plaintext, dependant on the
363 uchar *data_R, *data_G, *data_B;
369 load_RGB_pixmap("lena.ppm", &width, &height, &data_R, &data_G, &data_B);
370 imsize=width*height*3;
371 // load_RGB_pixmap("No_ecb_mode_picture.ppm", &width, &height, &data_R, &data_G, &data_B);
377 buffer=malloc(imsize*sizeof(uchar));
378 for(int i=0;i<imsize;i++) {
385 int oneD=width*height;
386 uchar *plaintext = malloc(imsize+1000); //add that for cbc
388 for(int i=0;i<oneD;i++) {
389 plaintext[i]=data_R[i];
390 plaintext[oneD+i]=data_G[i];
391 plaintext[2*oneD+i]=data_B[i];
396 for(int i=0;i<oneD;i++) {
397 plaintext[i]=buffer[i];
403 uchar *ciphertext = malloc(imsize+1000); //add that for cbc
405 /* Buffer for the decrypted text */
406 uchar *decryptedtext = malloc(imsize+1000); //add that for cbc
408 int decryptedtext_len, ciphertext_len;
410 /* Initialise the library */
411 /* ERR_load_crypto_strings();
412 OpenSSL_add_all_algorithms();
413 OPENSSL_config(NULL);
417 double time_encrypt=0;
418 double time_decrypt=0;
419 double t=TimeStart();
422 /* Encrypt the plaintext */
429 /* for(int i=0;i<16;i++)
430 printf("%d ",tag[i]);
433 for(i=0;i<nb_test;i++)
435 ciphertext_len = encryptccm (plaintext, imsize, plaintext, imsize, key, iv,
438 /*for(int i=0;i<16;i++) {
439 printf("%d ",tag[i]);
442 time_encrypt+=TimeStop(t);
444 // printf("Time encrypt %f\n",time);
445 printf("%e\t",(double)imsize*nb_test/time_encrypt);
448 for(int i=0;i<oneD;i++) {
449 data_R[i]=ciphertext[i];
450 data_G[i]=ciphertext[oneD+i];
451 data_B[i]=ciphertext[2*oneD+i];
453 store_RGB_pixmap("lena2.ppm", data_R, data_G, data_B, width, height);
462 for(int i=0;i<nb_test;i++)
464 /* Decrypt the ciphertext */
465 decryptedtext_len = decryptccm(ciphertext, ciphertext_len,ciphertext, ciphertext_len,tag, key, iv,
469 time_decrypt+=TimeStop(t);
471 //printf("Time decrypt %f\n",time);
472 printf("%e\t",(double)imsize*nb_test/time_decrypt);
475 for(int i=0;i<oneD;i++) {
476 data_R[i]=decryptedtext[i];
477 data_G[i]=decryptedtext[oneD+i];
478 data_B[i]=decryptedtext[2*oneD+i];
480 store_RGB_pixmap("lena3.ppm", data_R, data_G, data_B, width, height);
484 for(int i=0;i<imsize;i++) {
485 //cout<<(int)buffer[i]<<endl;
486 if(buffer[i]!=decryptedtext[i]) {
490 // printf("RESULT CORRECT: %d\n",equal);