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