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