svn update: 48539 (latest:48959)
[framework/uifw/eet.git] / src / lib / eet_cipher.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #ifdef HAVE_ALLOCA_H
6 # include <alloca.h>
7 #elif defined __GNUC__
8 # define alloca __builtin_alloca
9 #elif defined _AIX
10 # define alloca __alloca
11 #elif defined _MSC_VER
12 # include <malloc.h>
13 # define alloca _alloca
14 #else
15 # include <stddef.h>
16 # ifdef  __cplusplus
17 extern "C"
18 # endif
19 void *alloca (size_t);
20 #endif
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/mman.h>
27
28 #ifndef _MSC_VER
29 # include <unistd.h>
30 #endif
31
32 #ifdef HAVE_NETINET_IN_H
33 # include <netinet/in.h>
34 #endif
35
36 #ifdef HAVE_SIGNATURE
37 # ifdef HAVE_GNUTLS
38 #  include <gnutls/gnutls.h>
39 #  include <gnutls/x509.h>
40 # else
41 #  include <openssl/rsa.h>
42 #  include <openssl/objects.h>
43 #  include <openssl/err.h>
44 #  include <openssl/ssl.h>
45 #  include <openssl/dh.h>
46 #  include <openssl/dsa.h>
47 #  include <openssl/evp.h>
48 #  include <openssl/x509.h>
49 #  include <openssl/pem.h>
50 # endif
51 #endif
52
53 #ifdef HAVE_OPENSSL
54 #  include <openssl/sha.h>
55 #endif
56
57 #ifdef HAVE_CIPHER
58 # ifdef HAVE_GNUTLS
59 #  include <gnutls/x509.h>
60 #  include <gcrypt.h>
61 # else
62 #  include <openssl/evp.h>
63 #  include <openssl/hmac.h>
64 #  include <openssl/rand.h>
65 # endif
66 #endif
67
68 #include "Eet.h"
69 #include "Eet_private.h"
70
71 #define EET_MAGIC_SIGN 0x1ee74271
72
73 #ifdef HAVE_GNUTLS
74 # define MAX_KEY_LEN 32
75 # define MAX_IV_LEN 16
76 #else
77 # define MAX_KEY_LEN EVP_MAX_KEY_LENGTH
78 # define MAX_IV_LEN EVP_MAX_IV_LENGTH
79 #endif
80
81 #ifdef HAVE_CIPHER
82 # ifdef HAVE_GNUTLS
83 static Eet_Error eet_hmac_sha1(const void *key, size_t key_len, const void *data, size_t data_len, unsigned char *res);
84 # endif
85 static Eet_Error eet_pbkdf2_sha1(const char *key, int key_len, const unsigned char *salt, unsigned int salt_len, int iter, unsigned char *res, int res_len);
86 #endif
87
88 struct _Eet_Key
89 {
90    int          references;
91 #ifdef HAVE_SIGNATURE
92 # ifdef HAVE_GNUTLS
93    gnutls_x509_crt_t            certificate;
94    gnutls_x509_privkey_t        private_key;
95 # else
96    X509        *certificate;
97    EVP_PKEY    *private_key;
98 # endif
99 #endif
100 };
101
102 EAPI Eet_Key*
103 eet_identity_open(const char *certificate_file, const char *private_key_file, Eet_Key_Password_Callback cb)
104 {
105 #ifdef HAVE_SIGNATURE
106   /* Signature declarations */
107   Eet_Key *key = NULL;
108   FILE *fp = NULL;
109 # ifdef HAVE_GNUTLS
110   /* Gnutls private declarations */
111   int fd = -1;
112   struct stat st;
113   void *data = NULL;
114   gnutls_datum_t load_file = { NULL, 0 };
115   char pass[1024];
116
117   /* Init */
118   if (!(key = malloc(sizeof(Eet_Key)))) goto on_error;
119   key->references = 1;
120
121   if (gnutls_x509_crt_init(&(key->certificate))) goto on_error;
122   if (gnutls_x509_privkey_init(&(key->private_key))) goto on_error;
123
124   /* Mmap certificate_file */
125   if (!(fp = fopen(certificate_file, "r"))) goto on_error;
126   if ((fd = fileno(fp)) == -1) goto on_error;
127   if (fstat(fd, &st)) goto on_error;
128   if ((data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto on_error;
129
130   /* Import the certificate in Eet_Key structure */
131   load_file.data = data;
132   load_file.size = st.st_size;
133   if (gnutls_x509_crt_import(key->certificate, &load_file, GNUTLS_X509_FMT_PEM) < 0)
134     goto on_error;
135   if (munmap(data, st.st_size)) goto on_error;
136
137   /* Reset values */
138   fclose(fp);
139   fp = NULL;
140   data = NULL;
141   load_file.data = NULL;
142   load_file.size = 0;
143
144   /* Mmap private_key_file */
145   if (!(fp = fopen(private_key_file, "r"))) goto on_error;
146   if ((fd = fileno(fp)) == -1) goto on_error;
147   if (fstat(fd, &st)) goto on_error;
148   if ((data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) goto on_error;
149
150   /* Import the private key in Eet_Key structure */
151   load_file.data = data;
152   load_file.size = st.st_size;
153   /* Try to directly import the PEM encoded private key */
154   if (gnutls_x509_privkey_import(key->private_key, &load_file, GNUTLS_X509_FMT_PEM) < 0)
155     {
156       /* Else ask for the private key pass */
157       if (cb && cb(pass, 1024, 0, NULL))
158         {
159           /* If pass then try to decode the pkcs 8 private key */
160           if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file, GNUTLS_X509_FMT_PEM, pass, 0))
161             goto on_error;
162         }
163       else
164         {
165           /* Else try to import the pkcs 8 private key without pass */
166           if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file, GNUTLS_X509_FMT_PEM, NULL, 1))
167             goto on_error;
168         }
169     }
170   if (munmap(data, st.st_size)) goto on_error;
171   fclose(fp);
172
173   return key;
174
175  on_error:
176   if (fp) fclose(fp);
177   if (key)
178     {
179       if (key->certificate) gnutls_x509_crt_deinit(key->certificate);
180       if (key->private_key) gnutls_x509_privkey_deinit(key->private_key);
181       free(key);
182     }
183   if (data) munmap(data, st.st_size);
184 # else
185   /* Openssl private declarations */
186   EVP_PKEY *pkey = NULL;
187   X509 *cert = NULL;
188
189   /* Load the X509 certificate in memory. */
190   fp = fopen(certificate_file, "r");
191   if (!fp) return NULL;
192   cert = PEM_read_X509(fp, NULL, NULL, NULL);
193   fclose(fp);
194   if (!cert) goto on_error;
195
196   /* Check the presence of the public key. Just in case. */
197   pkey = X509_get_pubkey(cert);
198   if (!pkey) goto on_error;
199
200   /* Load the private key in memory. */
201   fp = fopen(private_key_file, "r");
202   if (!fp) goto on_error;
203   pkey = PEM_read_PrivateKey(fp, NULL, cb, NULL);
204   fclose(fp);
205   if (!pkey) goto on_error;
206
207   /* Load the certificate and the private key in Eet_Key structure */
208   key = malloc(sizeof(Eet_Key));
209   if (!key) goto on_error;
210   key->references = 1;
211   key->certificate = cert;
212   key->private_key = pkey;
213
214   return key;
215
216  on_error:
217   if (cert) X509_free(cert);
218   if (pkey) EVP_PKEY_free(pkey);
219 # endif
220 #endif
221   return NULL;
222 }
223
224 EAPI void
225 eet_identity_close(Eet_Key *key)
226 {
227 #ifdef HAVE_SIGNATURE
228   if (!key || (key->references > 0)) return ;
229 # ifdef HAVE_GNUTLS
230   gnutls_x509_crt_deinit(key->certificate);
231   gnutls_x509_privkey_deinit(key->private_key);
232 # else
233   X509_free(key->certificate);
234   EVP_PKEY_free(key->private_key);
235 # endif
236   free(key);
237 #endif
238 }
239
240 EAPI void
241 eet_identity_print(Eet_Key *key, FILE *out)
242 {
243 #ifdef HAVE_SIGNATURE
244 # ifdef HAVE_GNUTLS
245   const char    *names[6] = {
246     "Modulus",
247     "Public exponent",
248     "Private exponent",
249     "First prime",
250     "Second prime",
251     "Coefficient"
252   };
253   int err = 0;
254   gnutls_datum_t data = { NULL, 0 };
255   gnutls_datum_t rsa_raw[6];
256   size_t size = 128;
257   char *res = NULL;
258   char buf[33];
259   unsigned int i, j;
260
261   if (!key) return ;
262
263   if (key->private_key)
264     {
265       if (gnutls_x509_privkey_export_rsa_raw(key->private_key,
266                                              rsa_raw + 0,  /* Modulus */
267                                              rsa_raw + 1,  /* Public exponent */
268                                              rsa_raw + 2,  /* Private exponent */
269                                              rsa_raw + 3,  /* First prime */
270                                              rsa_raw + 4,  /* Second prime */
271                                              rsa_raw + 5)) /* Coefficient */
272         goto on_error;
273       if (!(res = malloc(size))) goto on_error;
274
275       fprintf(out, "Private Key:\n");
276       buf[32] = '\0';
277
278       for (i = 0; i < 6; i++)
279         {
280           while ((err = gnutls_hex_encode(rsa_raw + i, res, &size)) == GNUTLS_E_SHORT_MEMORY_BUFFER)
281             {
282               size += 128;
283               if (!(res = realloc(res, size))) goto on_error;
284             }
285           if (err) goto on_error;
286
287           fprintf(out, "\t%s:\n", names[i]);
288           for (j = 0; strlen(res) > j; j += 32)
289             {
290               snprintf(buf, 32, "%s", res + j);
291               fprintf(out, "\t\t%s\n", buf);
292             }
293         }
294       free(res);
295       res = NULL;
296     }
297
298   if (key->certificate)
299     {
300       fprintf(out, "Public certificate:\n");
301       if (gnutls_x509_crt_print(key->certificate, GNUTLS_X509_CRT_FULL, &data)) goto on_error;
302       fprintf(out, "%s\n", data.data);
303       gnutls_free(data.data);
304       data.data = NULL;
305     }
306
307  on_error:
308   if (res) free(res);
309   if (data.data) gnutls_free(data.data);
310   return ;
311 # else
312   RSA *rsa;
313   DSA *dsa;
314   DH *dh;
315
316   if (!key) return ;
317
318   rsa = EVP_PKEY_get1_RSA(key->private_key);
319   if (rsa)
320     {
321       fprintf(out, "Private key (RSA):\n");
322       RSA_print_fp(out, rsa, 0);
323     }
324
325   dsa = EVP_PKEY_get1_DSA(key->private_key);
326   if (dsa)
327     {
328       fprintf(out, "Private key (DSA):\n");
329       DSA_print_fp(out, dsa, 0);
330     }
331
332   dh = EVP_PKEY_get1_DH(key->private_key);
333   if (dh)
334     {
335       fprintf(out, "Private key (DH):\n");
336       DHparams_print_fp(out, dh);
337     }
338
339   fprintf(out, "Public certificate:\n");
340   X509_print_fp(out, key->certificate);
341 # endif
342 #else
343   ERR("You need to compile signature support in EET.");
344 #endif
345 }
346
347 void
348 eet_identity_ref(Eet_Key *key)
349 {
350    if (key == NULL) return ;
351    key->references++;
352 }
353
354 void
355 eet_identity_unref(Eet_Key *key)
356 {
357    if (key == NULL) return ;
358    key->references--;
359    eet_identity_close(key);
360 }
361
362 void *
363 eet_identity_compute_sha1(const void *data_base, unsigned int data_length,
364                           int *sha1_length)
365 {
366    void *result;
367
368 #ifdef HAVE_SIGNATURE
369 #  ifdef HAVE_GNUTLS
370    result = malloc(gcry_md_get_algo_dlen(GCRY_MD_SHA1));
371    if (!result) return NULL;
372
373    gcry_md_hash_buffer(GCRY_MD_SHA1, result, data_base, data_length);
374    if (sha1_length) *sha1_length = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
375 #  else
376 #   ifdef HAVE_OPENSSL
377    result = malloc(SHA_DIGEST_LENGTH);
378    if (!result) return NULL;
379
380    SHA1(data_base, data_length, result);
381    if (sha1_length) *sha1_length = SHA_DIGEST_LENGTH;
382 #   else
383    result = NULL;
384 #   endif
385 #  endif
386 #else
387    result = NULL;
388 #endif
389
390    return result;
391 }
392
393 Eet_Error
394 eet_identity_sign(FILE *fp, Eet_Key *key)
395 {
396 #ifdef HAVE_SIGNATURE
397    Eet_Error err = EET_ERROR_NONE;
398    struct stat st_buf;
399    void *data;
400    int fd;
401    int head[3];
402    unsigned char *sign = NULL;
403    unsigned char *cert = NULL;
404 # ifdef HAVE_GNUTLS
405    gnutls_datum_t datum = { NULL, 0 };
406    size_t sign_len = 0;
407    size_t cert_len = 0;
408 # else
409    EVP_MD_CTX md_ctx;
410    unsigned int sign_len = 0;
411    int cert_len = 0;
412 # endif
413
414    /* A few check and flush pending write. */
415    if (!fp || !key || !key->certificate || !key->private_key)
416      return EET_ERROR_BAD_OBJECT;
417
418    /* Get the file size. */
419    fd = fileno(fp);
420    if (fd < 0) return EET_ERROR_BAD_OBJECT;
421    if (fstat(fd, &st_buf) < 0) return EET_ERROR_MMAP_FAILED;
422
423    /* Map the file in memory. */
424    data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
425    if (data == MAP_FAILED) return EET_ERROR_MMAP_FAILED;
426
427 # ifdef HAVE_GNUTLS
428    datum.data = data;
429    datum.size = st_buf.st_size;
430
431    /* Get the signature length */
432    if (gnutls_x509_privkey_sign_data(key->private_key, GNUTLS_DIG_SHA1, 0, &datum, sign, &sign_len) &&
433        !sign_len)
434      {
435        err = EET_ERROR_SIGNATURE_FAILED;
436        goto on_error;
437      }
438
439    /* Get the signature */
440    sign = malloc(sign_len);
441    if (!sign || gnutls_x509_privkey_sign_data(key->private_key, GNUTLS_DIG_SHA1, 0, &datum, sign, &sign_len))
442      {
443        if (!sign) err = EET_ERROR_OUT_OF_MEMORY;
444        else err = EET_ERROR_SIGNATURE_FAILED;
445        goto on_error;
446      }
447
448    /* Get the certificate length */
449    if (gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert, &cert_len) &&
450        !cert_len)
451      {
452        err = EET_ERROR_SIGNATURE_FAILED;
453        goto on_error;
454      }
455
456    /* Get the certificate */
457    cert = malloc(cert_len);
458    if (!cert || gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert, &cert_len))
459      {
460        if (!cert) err = EET_ERROR_OUT_OF_MEMORY;
461        else err = EET_ERROR_SIGNATURE_FAILED;
462        goto on_error;
463      }
464 # else
465    sign_len = EVP_PKEY_size(key->private_key);
466    sign = malloc(sign_len);
467    if (sign == NULL)
468      {
469         err = EET_ERROR_OUT_OF_MEMORY;
470         goto on_error;
471      }
472
473    /* Do the signature. */
474    EVP_SignInit(&md_ctx, EVP_sha1());
475    EVP_SignUpdate(&md_ctx, data, st_buf.st_size);
476    err = EVP_SignFinal(&md_ctx, sign, (unsigned int *)&sign_len, key->private_key);
477    if (err != 1)
478      {
479         ERR_print_errors_fp(stdout);
480         err = EET_ERROR_SIGNATURE_FAILED;
481         goto on_error;
482      }
483
484    /* Give me the der (binary form for X509). */
485    cert_len = i2d_X509(key->certificate, &cert);
486    if (cert_len < 0)
487      {
488         ERR_print_errors_fp(stdout);
489         err = EET_ERROR_X509_ENCODING_FAILED;
490         goto on_error;
491      }
492 # endif
493    /* Append the signature at the end of the file. */
494    head[0] = (int) htonl ((unsigned int) EET_MAGIC_SIGN);
495    head[1] = (int) htonl ((unsigned int) sign_len);
496    head[2] = (int) htonl ((unsigned int) cert_len);
497
498    if (fwrite(head, sizeof(head), 1, fp) != 1)
499      {
500         err = EET_ERROR_WRITE_ERROR;
501         goto on_error;
502      }
503    if (fwrite(sign, sign_len, 1, fp) != 1)
504      {
505         err = EET_ERROR_WRITE_ERROR;
506         goto on_error;
507      }
508    if (fwrite(cert, cert_len, 1, fp) != 1)
509      {
510         err = EET_ERROR_WRITE_ERROR;
511         goto on_error;
512      }
513
514  on_error:
515 # ifdef HAVE_GNUTLS
516    if (cert) free(cert);
517 # else
518    if (cert) OPENSSL_free(cert);
519 # endif
520    if (sign) free(sign);
521    munmap(data, st_buf.st_size);
522    return err;
523 #else
524    return EET_ERROR_NOT_IMPLEMENTED;
525 #endif
526 }
527
528 const void*
529 eet_identity_check(const void *data_base, unsigned int data_length,
530                    void **sha1, int *sha1_length,
531                    const void *signature_base, unsigned int signature_length,
532                    const void **raw_signature_base, unsigned int *raw_signature_length,
533                    int *x509_length)
534 {
535 #ifdef HAVE_SIGNATURE
536    const int *header = signature_base;
537    const unsigned char *sign;
538    const unsigned char *cert_der;
539    int sign_len;
540    int cert_len;
541    int magic;
542
543    /* At least the header size */
544    if (signature_length < sizeof(int) * 3) return NULL;
545
546    /* Get the header */
547    magic = ntohl(header[0]);
548    sign_len = ntohl(header[1]);
549    cert_len = ntohl(header[2]);
550
551    /* Verify the header */
552    if (magic != EET_MAGIC_SIGN) return NULL;
553    if (sign_len + cert_len + sizeof(int) * 3 > signature_length) return NULL;
554
555    /* Update the signature and certificate pointer */
556    sign = (unsigned char *)signature_base + sizeof(int) * 3;
557    cert_der = sign + sign_len;
558
559 # ifdef HAVE_GNUTLS
560    gnutls_x509_crt_t cert;
561    gnutls_datum_t datum;
562    gnutls_datum_t signature;
563 #  if EET_USE_NEW_GNUTLS_API
564    unsigned char *hash;
565    gcry_md_hd_t md;
566    int err;
567 #  endif
568
569    /* Create an understanding certificate structure for gnutls */
570    datum.data = (void *)cert_der;
571    datum.size = cert_len;
572    gnutls_x509_crt_init(&cert);
573    gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER);
574
575    signature.data = (void *)sign;
576    signature.size = sign_len;
577
578    /* Verify the signature */
579 #  if EET_USE_NEW_GNUTLS_API
580    /*
581      I am waiting for my patch being accepted in GnuTLS release.
582      But we now have a way to prevent double computation of SHA1.
583     */
584    err = gcry_md_open (&md, GCRY_MD_SHA1, 0);
585    if (err < 0) return NULL;
586
587    gcry_md_write(md, data_base, data_length);
588
589    hash = gcry_md_read(md, GCRY_MD_SHA1);
590    if (hash == NULL)
591      {
592         gcry_md_close(md);
593         return NULL;
594      }
595
596    datum.size = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
597    datum.data = hash;
598
599    if (!gnutls_x509_crt_verify_hash(cert, 0, &datum, &signature))
600      {
601         gcry_md_close(md);
602         return NULL;
603      }
604
605    if (sha1)
606      {
607         *sha1 = malloc(datum.size);
608         if (!*sha1)
609           {
610              gcry_md_close(md);
611              return NULL;
612           }
613
614         memcpy(*sha1, hash, datum.size);
615         *sha1_length = datum.size;
616      }
617
618    gcry_md_close(md);
619 #  else
620    datum.data = (void *)data_base;
621    datum.size = data_length;
622
623    if (!gnutls_x509_crt_verify_data(cert, 0, &datum, &signature))
624      return NULL;
625
626    if (sha1)
627      {
628         *sha1 = NULL;
629         *sha1_length = -1;
630      }
631 #  endif
632   gnutls_x509_crt_deinit(cert);
633
634 # else
635    const unsigned char *tmp;
636    EVP_PKEY *pkey;
637    X509 *x509;
638    EVP_MD_CTX md_ctx;
639    int err;
640
641    /* Strange but d2i_X509 seems to put 0 all over the place. */
642    tmp = alloca(cert_len);
643    memcpy((char*) tmp, cert_der, cert_len);
644    x509 = d2i_X509(NULL, &tmp, cert_len);
645    if (x509 == NULL) return NULL;
646
647    /* Get public key - eay */
648    pkey=X509_get_pubkey(x509);
649    if (pkey == NULL)
650      {
651         X509_free(x509);
652         return NULL;
653      }
654
655    /* Verify the signature */
656    EVP_VerifyInit(&md_ctx, EVP_sha1());
657    EVP_VerifyUpdate(&md_ctx, data_base, data_length);
658    err = EVP_VerifyFinal(&md_ctx, sign, sign_len, pkey);
659
660    X509_free(x509);
661    EVP_PKEY_free(pkey);
662
663    if (sha1)
664      {
665         *sha1 = NULL;
666         *sha1_length = -1;
667      }
668
669    if (err != 1)
670      return NULL;
671 # endif
672    if (x509_length) *x509_length = cert_len;
673    if (raw_signature_base) *raw_signature_base = sign;
674    if (raw_signature_length) *raw_signature_length = sign_len;
675    return cert_der;
676 #else
677    return NULL;
678 #endif
679 }
680
681 EAPI void
682 eet_identity_certificate_print(const unsigned char *certificate, int der_length, FILE *out)
683 {
684 #ifdef HAVE_SIGNATURE
685   if (!certificate || !out || der_length <= 0)
686      {
687         ERR("No certificate provided.");
688         return ;
689      }
690 # ifdef HAVE_GNUTLS
691   gnutls_datum_t datum;
692   gnutls_x509_crt_t cert;
693
694   /* Create an understanding certificate structure for gnutls */
695   datum.data = (void *)certificate;
696   datum.size = der_length;
697   if (gnutls_x509_crt_init(&cert)) goto on_error;
698   if (gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER)) goto on_error;
699
700   /* Pretty print the certificate */
701   datum.data = NULL;
702   datum.size = 0;
703   if (gnutls_x509_crt_print(cert, GNUTLS_X509_CRT_FULL, &datum)) goto on_error;
704   INF("Public certificate :");
705   INF("%s", datum.data);
706
707  on_error:
708   if (datum.data) gnutls_free(datum.data);
709   gnutls_x509_crt_deinit(cert);
710 # else
711    const unsigned char *tmp;
712    X509 *x509;
713
714    /* Strange but d2i_X509 seems to put 0 all over the place. */
715    tmp = alloca(der_length);
716    memcpy((char*) tmp, certificate, der_length);
717    x509 = d2i_X509(NULL, &tmp, der_length);
718    if (x509 == NULL)
719      {
720         INF("Not a valid certificate.");
721         return ;
722      }
723
724    INF("Public certificate :");
725    X509_print_fp(out, x509);
726
727    X509_free(x509);
728 # endif
729 #else
730    ERR("You need to compile signature support in EET.");
731 #endif
732 }
733
734 Eet_Error
735 eet_cipher(const void *data, unsigned int size, const char *key, unsigned int length, void **result, unsigned int *result_length)
736 {
737 #ifdef HAVE_CIPHER
738   /* Cipher declarations */
739    unsigned int *ret = NULL;
740    unsigned char iv[MAX_IV_LEN];
741    unsigned char ik[MAX_KEY_LEN];
742    unsigned char key_material[MAX_IV_LEN + MAX_KEY_LEN];
743    unsigned int salt;
744    unsigned int tmp = 0;
745    int crypted_length;
746    int opened = 0;
747 # ifdef HAVE_GNUTLS
748    /* Gcrypt declarations */
749    gcry_error_t err = 0;
750    gcry_cipher_hd_t cipher;
751 # else
752    /* Openssl declarations*/
753    EVP_CIPHER_CTX ctx;
754    unsigned int *buffer;
755    int tmp_len;
756 # endif
757
758 # ifdef HAVE_GNUTLS
759    /* Gcrypt salt generation */
760    gcry_create_nonce((unsigned char *)&salt, sizeof(salt));
761 # else
762    /* Openssl salt generation */
763    if (!RAND_bytes((unsigned char*)&salt, sizeof (unsigned int)))
764      return EET_ERROR_PRNG_NOT_SEEDED;
765 #endif
766
767    eet_pbkdf2_sha1(key, length, (unsigned char *)&salt, sizeof(unsigned int), 2048, key_material, MAX_KEY_LEN + MAX_IV_LEN);
768
769    memcpy(iv, key_material, MAX_IV_LEN);
770    memcpy(ik, key_material + MAX_IV_LEN, MAX_KEY_LEN);
771
772    memset(key_material, 0, sizeof (key_material));
773
774    crypted_length = ((((size + sizeof (unsigned int)) >> 5) + 1) << 5);
775    ret = malloc(crypted_length + sizeof(unsigned int));
776    if (!ret) {
777       memset(iv, 0, sizeof (iv));
778       memset(ik, 0, sizeof (ik));
779       memset(&salt, 0, sizeof (salt));
780       return EET_ERROR_OUT_OF_MEMORY;
781    }
782
783    *ret = salt;
784    memset(&salt, 0, sizeof (salt));
785    tmp = htonl(size);
786
787 #ifdef HAVE_GNUTLS
788    *(ret + 1) = tmp;
789    memcpy(ret + 2, data, size);
790
791    /* Gcrypt create the corresponding cipher
792       AES with a 256 bit key, Cipher Block Chaining mode */
793    err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
794    if (err) goto on_error;
795    opened = 1;
796    err = gcry_cipher_setiv(cipher, iv, MAX_IV_LEN);
797    if (err) goto on_error;
798    err = gcry_cipher_setkey(cipher, ik, MAX_KEY_LEN);
799    if (err) goto on_error;
800
801    memset(iv, 0, sizeof (iv));
802    memset(ik, 0, sizeof (ik));
803
804    /* Gcrypt encrypt */
805    err = gcry_cipher_encrypt(cipher, (unsigned char *)(ret + 1), crypted_length, NULL, 0);
806    if (err) goto on_error;
807
808    /* Gcrypt close the cipher */
809    gcry_cipher_close(cipher);
810 # else
811    buffer = alloca(crypted_length);
812    *buffer = tmp;
813
814    memcpy(buffer + 1, data, size);
815
816    /* Openssl create the corresponding cipher
817       AES with a 256 bit key, Cipher Block Chaining mode */
818    EVP_CIPHER_CTX_init(&ctx);
819    if (!EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, ik, iv)) goto on_error;
820    opened = 1;
821
822    memset(iv, 0, sizeof (iv));
823    memset(ik, 0, sizeof (ik));
824
825    /* Openssl encrypt */
826    if (!EVP_EncryptUpdate(&ctx, (unsigned char*)(ret + 1), &tmp_len, (unsigned char*) buffer, size + sizeof (unsigned int)))
827      goto on_error;
828
829    /* Openssl close the cipher */
830    if (!EVP_EncryptFinal_ex(&ctx, ((unsigned char*)(ret + 1)) + tmp_len, &tmp_len))
831      goto on_error;
832    EVP_CIPHER_CTX_cleanup(&ctx);
833 # endif
834
835    /* Set return values */
836    if (result_length) *result_length = crypted_length + sizeof(unsigned int);
837    if (result) *result = ret;
838    else free(ret);
839
840    return EET_ERROR_NONE;
841
842  on_error:
843    memset(iv, 0, sizeof (iv));
844    memset(ik, 0, sizeof (ik));
845
846 # ifdef HAVE_GNUTLS
847    /* Gcrypt error */
848    if (opened) gcry_cipher_close(cipher);
849 # else
850    /* Openssl error */
851    if (opened) EVP_CIPHER_CTX_cleanup(&ctx);
852 # endif
853    /* General error */
854    if (ret) free(ret);
855    if (result) *result = NULL;
856    if (result_length) *result_length = 0;
857
858    return EET_ERROR_ENCRYPT_FAILED;
859 #else
860    /* Cipher not supported */
861    (void) data;
862    (void) size;
863    (void) key;
864    (void) length;
865    (void) result;
866    (void) result_length;
867    return EET_ERROR_NOT_IMPLEMENTED;
868 #endif
869 }
870
871 Eet_Error
872 eet_decipher(const void *data, unsigned int size, const char *key, unsigned int length, void **result, unsigned int *result_length)
873 {
874 #ifdef HAVE_CIPHER
875    const unsigned int *over = data;
876    unsigned int *ret = NULL;
877    unsigned char ik[MAX_KEY_LEN];
878    unsigned char iv[MAX_IV_LEN];
879    unsigned char key_material[MAX_KEY_LEN + MAX_IV_LEN];
880    unsigned int salt;
881    int tmp_len;
882    int tmp = 0;
883
884    /* At least the salt and an AES block */
885    if (size < sizeof(unsigned int) + 16) return EET_ERROR_BAD_OBJECT;
886
887    /* Get the salt */
888    salt = *over;
889
890    /* Generate the iv and the key with the salt */
891    eet_pbkdf2_sha1(key, length, (unsigned char *)&salt, sizeof(unsigned int), 2048, key_material, MAX_KEY_LEN + MAX_IV_LEN);
892
893    memcpy(iv, key_material, MAX_IV_LEN);
894    memcpy(ik, key_material + MAX_IV_LEN, MAX_KEY_LEN);
895
896    memset(key_material, 0, sizeof (key_material));
897    memset(&salt, 0, sizeof (salt));
898
899    /* Align to AES block size if size is not align */
900    tmp_len = size - sizeof (unsigned int);
901    if ((tmp_len & 0x1F) != 0) goto on_error;
902
903    ret = malloc(tmp_len);
904    if (!ret) goto on_error;
905
906 # ifdef HAVE_GNUTLS
907    gcry_error_t err = 0;
908    gcry_cipher_hd_t cipher;
909
910    /* Gcrypt create the corresponding cipher */
911    err = gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC, 0);
912    if (err) return EET_ERROR_DECRYPT_FAILED;
913    err = gcry_cipher_setiv(cipher, iv, MAX_IV_LEN);
914    if (err) goto on_error;
915    err = gcry_cipher_setkey(cipher, ik, MAX_KEY_LEN);
916    if (err) goto on_error;
917
918    memset(iv, 0, sizeof (iv));
919    memset(ik, 0, sizeof (ik));
920
921    /* Gcrypt decrypt */
922    err = gcry_cipher_decrypt(cipher, ret, tmp_len, ((unsigned int *)data) + 1, tmp_len);
923    if (err) goto on_error;
924
925    /* Gcrypt close the cipher */
926    gcry_cipher_close(cipher);
927
928 # else
929    EVP_CIPHER_CTX ctx;
930    int opened = 0;
931
932    /* Openssl create the corresponding cipher */
933    EVP_CIPHER_CTX_init(&ctx);
934    opened = 1;
935
936    if (!EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, ik, iv))
937      goto on_error;
938
939    memset(iv, 0, sizeof (iv));
940    memset(ik, 0, sizeof (ik));
941
942    /* Openssl decrypt */
943    if (!EVP_DecryptUpdate(&ctx, (unsigned char *) ret, &tmp,
944                           (unsigned char *) (over + 1), tmp_len))
945      goto on_error;
946
947    /* Openssl close the cipher*/
948    EVP_CIPHER_CTX_cleanup(&ctx);
949 # endif
950    /* Get the decrypted data size */
951    tmp = *ret;
952    tmp = ntohl(tmp);
953    if (tmp > tmp_len) goto on_error;
954
955    /* Update the return values */
956    if (result_length) *result_length = tmp;
957    if (result)
958      {
959        *result = NULL;
960        *result = malloc(tmp);
961        if (!*result)
962          goto on_error;
963        memcpy(*result, ret + 1, tmp);
964      }
965    free(ret);
966
967    return EET_ERROR_NONE;
968
969  on_error:
970    memset(iv, 0, sizeof (iv));
971    memset(ik, 0, sizeof (ik));
972
973 # ifdef HAVE_GNUTLS
974 # else
975    if (opened) EVP_CIPHER_CTX_cleanup(&ctx);
976 # endif
977    if (result) *result = NULL;
978    if (result_length) *result_length = 0;
979    if (ret) free(ret);
980
981    return EET_ERROR_DECRYPT_FAILED;
982 #else
983    (void) data;
984    (void) size;
985    (void) key;
986    (void) length;
987    (void) result;
988    (void) result_length;
989    return EET_ERROR_NOT_IMPLEMENTED;
990 #endif
991 }
992
993 #ifdef HAVE_CIPHER
994 # ifdef HAVE_GNUTLS
995 static Eet_Error
996 eet_hmac_sha1(const void *key, size_t key_len,
997               const void *data, size_t data_len, unsigned char *res)
998 {
999   size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
1000   gcry_md_hd_t mdh;
1001   unsigned char *hash;
1002   gpg_error_t err;
1003
1004   err = gcry_md_open(&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
1005   if (err != GPG_ERR_NO_ERROR)
1006     return 1;
1007
1008   err = gcry_md_setkey(mdh, key, key_len);
1009   if (err != GPG_ERR_NO_ERROR)
1010     {
1011       gcry_md_close(mdh);
1012       return 1;
1013     }
1014
1015   gcry_md_write(mdh, data, data_len);
1016
1017   hash = gcry_md_read(mdh, GCRY_MD_SHA1);
1018   if (hash == NULL)
1019     {
1020       gcry_md_close(mdh);
1021       return 1;
1022     }
1023
1024   memcpy(res, hash, hlen);
1025
1026   gcry_md_close(mdh);
1027
1028   return 0;
1029 }
1030 # endif
1031
1032 static Eet_Error
1033 eet_pbkdf2_sha1(const char          *key,
1034                 int                  key_len,
1035                 const unsigned char *salt,
1036                 unsigned int         salt_len,
1037                 int                  iter,
1038                 unsigned char       *res,
1039                 int                  res_len)
1040 {
1041   unsigned char         digest[20];
1042   unsigned char         tab[4];
1043   unsigned char        *p = res;
1044   unsigned char        *buf;
1045   unsigned long         i;
1046   int                   digest_len = 20;
1047   int                   len = res_len;
1048   int                   tmp_len;
1049   int                   j, k;
1050 # ifdef HAVE_GNUTLS
1051 # else
1052   HMAC_CTX              hctx;
1053 # endif
1054
1055   buf = alloca(salt_len + 4);
1056   if (!buf) return 1;
1057
1058   for (i = 1; len; len -= tmp_len, p += tmp_len, i++)
1059     {
1060       if (len > digest_len) tmp_len = digest_len;
1061       else tmp_len = len;
1062
1063       tab[0] = (unsigned char)(i & 0xff000000) >> 24;
1064       tab[1] = (unsigned char)(i & 0x00ff0000) >> 16;
1065       tab[2] = (unsigned char)(i & 0x0000ff00) >> 8;
1066       tab[3] = (unsigned char)(i & 0x000000ff) >> 0;
1067
1068 # ifdef HAVE_GNUTLS
1069       memcpy(buf, salt, salt_len);
1070       memcpy(buf + salt_len, tab, 4);
1071       eet_hmac_sha1(key, key_len, buf, salt_len + 4, digest);
1072 # else
1073       HMAC_Init(&hctx, key, key_len, EVP_sha1());
1074       HMAC_Update(&hctx, salt, salt_len);
1075       HMAC_Update(&hctx, tab, 4);
1076       HMAC_Final(&hctx, digest, NULL);
1077 # endif
1078       memcpy(p, digest, tmp_len);
1079
1080       for (j = 1; j < iter; j++)
1081         {
1082 # ifdef HAVE_GNUTLS
1083           eet_hmac_sha1(key, key_len, digest, 20, digest);
1084 # else
1085           HMAC(EVP_sha1(), key, key_len, digest, 20, digest, NULL);
1086 # endif
1087           for (k = 0; k < tmp_len; k++)
1088             p[k] ^= digest[k];
1089         }
1090     }
1091
1092 # ifdef HAVE_GNUTLS
1093 # else
1094   HMAC_cleanup(&hctx);
1095 # endif
1096   return 0;
1097 }
1098 #endif