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