1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif /* ifdef HAVE_CONFIG_H */
4 
5 #include <stdio.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <unistd.h>
10 
11 #ifdef HAVE_SIGNATURE
12 # ifdef _WIN32
13 #  include <evil_private.h> /* mmap */
14 # else
15 #  include <sys/mman.h>
16 # endif
17 # ifdef HAVE_GNUTLS
18 #  include <gnutls/gnutls.h>
19 #  include <gnutls/x509.h>
20 # else /* ifdef HAVE_GNUTLS */
21 #  include <openssl/rsa.h>
22 #  include <openssl/objects.h>
23 #  include <openssl/err.h>
24 #  include <openssl/ssl.h>
25 #  include <openssl/dh.h>
26 #  include <openssl/dsa.h>
27 #  include <openssl/evp.h>
28 #  include <openssl/x509.h>
29 #  include <openssl/pem.h>
30 # endif /* ifdef HAVE_GNUTLS */
31 #endif /* ifdef HAVE_SIGNATURE */
32 
33 #ifdef HAVE_OPENSSL
34 # include <openssl/sha.h>
35 #endif /* ifdef HAVE_OPENSSL */
36 
37 #ifdef HAVE_CIPHER
38 # ifdef HAVE_GNUTLS
39 #  include <gnutls/abstract.h>
40 #  include <gnutls/x509.h>
41 #  include <gcrypt.h>
42 # else /* ifdef HAVE_GNUTLS */
43 #  include <openssl/evp.h>
44 #  include <openssl/hmac.h>
45 #  include <openssl/rand.h>
46 # endif /* ifdef HAVE_GNUTLS */
47 #endif /* ifdef HAVE_CIPHER */
48 
49 #include <Emile.h>
50 
51 #include "Eet.h"
52 #include "Eet_private.h"
53 
54 #ifdef HAVE_GNUTLS
55 # define MAX_KEY_LEN   32
56 # define MAX_IV_LEN    16
57 #else /* ifdef HAVE_GNUTLS */
58 # define MAX_KEY_LEN   EVP_MAX_KEY_LENGTH
59 # define MAX_IV_LEN    EVP_MAX_IV_LENGTH
60 #endif /* ifdef HAVE_GNUTLS */
61 
62 struct _Eet_Key
63 {
64    int                   references;
65 #ifdef HAVE_SIGNATURE
66 # ifdef HAVE_GNUTLS
67    gnutls_x509_crt_t     certificate;
68    gnutls_x509_privkey_t private_key;
69 # else /* ifdef HAVE_GNUTLS */
70    X509                 *certificate;
71    EVP_PKEY             *private_key;
72 # endif /* ifdef HAVE_GNUTLS */
73 #endif /* ifdef HAVE_SIGNATURE */
74 };
75 
76 EAPI Eet_Key *
eet_identity_open(const char * certificate_file,const char * private_key_file,Eet_Key_Password_Callback cb)77 eet_identity_open(const char               *certificate_file,
78                   const char               *private_key_file,
79                   Eet_Key_Password_Callback cb)
80 {
81 #ifdef HAVE_SIGNATURE
82    /* Signature declarations */
83    Eet_Key *key = NULL;
84 # ifdef HAVE_GNUTLS
85    /* Gnutls private declarations */
86    Eina_File *f = NULL;
87    void *data = NULL;
88    gnutls_datum_t load_file = { NULL, 0 };
89    char pass[1024];
90 
91    if (!emile_cipher_init()) return NULL;
92 
93    /* Init */
94    if (!(key = malloc(sizeof(Eet_Key))))
95      goto on_error;
96 
97    key->references = 1;
98 
99    if (gnutls_x509_crt_init(&(key->certificate)))
100      goto on_error;
101 
102    if (gnutls_x509_privkey_init(&(key->private_key)))
103      goto on_error;
104 
105    /* Mmap certificate_file */
106    f = eina_file_open(certificate_file, 0);
107    if (!f)
108      goto on_error;
109 
110    /* let's make mmap safe and just get 0 pages for IO erro */
111    eina_mmap_safety_enabled_set(EINA_TRUE);
112 
113    data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
114    if (!data) goto on_error;
115 
116    /* Import the certificate in Eet_Key structure */
117    load_file.data = data;
118    load_file.size = eina_file_size_get(f);
119    if (gnutls_x509_crt_import(key->certificate, &load_file,
120                               GNUTLS_X509_FMT_PEM) < 0)
121      goto on_error;
122 
123    eina_file_map_free(f, data);
124 
125    /* Reset values */
126    eina_file_close(f);
127    f = NULL;
128    data = NULL;
129    load_file.data = NULL;
130    load_file.size = 0;
131 
132    /* Mmap private_key_file */
133    f = eina_file_open(private_key_file, 0);
134    if (!f)
135      goto on_error;
136 
137    /* let's make mmap safe and just get 0 pages for IO erro */
138    eina_mmap_safety_enabled_set(EINA_TRUE);
139 
140    data = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
141    if (!data)
142      goto on_error;
143 
144    /* Import the private key in Eet_Key structure */
145    load_file.data = data;
146    load_file.size = eina_file_size_get(f);
147    /* Try to directly import the PEM encoded private key */
148    if (gnutls_x509_privkey_import(key->private_key, &load_file,
149                                   GNUTLS_X509_FMT_PEM) < 0)
150      {
151         /* Else ask for the private key pass */
152          if (cb && cb(pass, 1024, 0, NULL))
153            {
154      /* If pass then try to decode the pkcs 8 private key */
155                if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file,
156                                                     GNUTLS_X509_FMT_PEM, pass, 0))
157                  goto on_error;
158            }
159          else
160          /* Else try to import the pkcs 8 private key without pass */
161          if (gnutls_x509_privkey_import_pkcs8(key->private_key, &load_file,
162                                               GNUTLS_X509_FMT_PEM, NULL, 1))
163            goto on_error;
164      }
165 
166    eina_file_map_free(f, data);
167    eina_file_close(f);
168 
169    return key;
170 
171 on_error:
172    if (data) eina_file_map_free(f, data);
173    if (f) eina_file_close(f);
174 
175    if (key)
176      {
177         if (key->certificate)
178           gnutls_x509_crt_deinit(key->certificate);
179 
180         if (key->private_key)
181           gnutls_x509_privkey_deinit(key->private_key);
182 
183         free(key);
184      }
185 
186 # else /* ifdef HAVE_GNUTLS */
187    /* Openssl private declarations */
188    EVP_PKEY *pkey = NULL;
189    X509 *cert = NULL;
190 
191    if (!emile_cipher_init()) return NULL;
192 
193    /* Load the X509 certificate in memory. */
194    {
195       BIO* cert_bio = BIO_new_file(certificate_file, "rb");
196       cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL);
197       BIO_free(cert_bio);
198       if (!cert)
199         goto on_error;
200    }
201 
202    /* Check the presence of the public key. Just in case. */
203    pkey = X509_get_pubkey(cert);
204    if (!pkey)
205      goto on_error;
206 
207    /* Load the private key in memory. */
208    {
209       BIO* private_key_bio = BIO_new_file(private_key_file, "rb");
210       pkey = PEM_read_bio_PrivateKey(private_key_bio, NULL, cb, NULL);
211       BIO_free(private_key_bio);
212       if (!pkey)
213         goto on_error;
214    }
215 
216    /* Load the certificate and the private key in Eet_Key structure */
217    key = malloc(sizeof(Eet_Key));
218    if (!key)
219      goto on_error;
220 
221    key->references = 1;
222    key->certificate = cert;
223    key->private_key = pkey;
224 
225    return key;
226 
227 on_error:
228    if (cert)
229      X509_free(cert);
230 
231    if (pkey)
232      EVP_PKEY_free(pkey);
233 
234 # endif /* ifdef HAVE_GNUTLS */
235 #else
236    (void) certificate_file;
237    (void) private_key_file;
238    (void) cb;
239 #endif /* ifdef HAVE_SIGNATURE */
240    return NULL;
241 }
242 
243 EAPI void
eet_identity_close(Eet_Key * key)244 eet_identity_close(Eet_Key *key)
245 {
246    if (!emile_cipher_init()) return ;
247 
248 #ifdef HAVE_SIGNATURE
249    if (!key || (key->references > 0))
250      return;
251 
252 # ifdef HAVE_GNUTLS
253    gnutls_x509_crt_deinit(key->certificate);
254    gnutls_x509_privkey_deinit(key->private_key);
255 # else /* ifdef HAVE_GNUTLS */
256    X509_free(key->certificate);
257    EVP_PKEY_free(key->private_key);
258 # endif /* ifdef HAVE_GNUTLS */
259    free(key);
260 # else
261    (void)key;
262 #endif /* ifdef HAVE_SIGNATURE */
263 }
264 
265 EAPI void
eet_identity_print(Eet_Key * key,FILE * out)266 eet_identity_print(Eet_Key *key,
267                    FILE    *out)
268 {
269 #ifdef HAVE_SIGNATURE
270 # ifdef HAVE_GNUTLS
271    const char *names[6] = {
272       "Modulus",
273       "Public exponent",
274       "Private exponent",
275       "First prime",
276       "Second prime",
277       "Coefficient"
278    };
279    int err = 0;
280    gnutls_datum_t data = { NULL, 0 };
281    gnutls_datum_t rsa_raw[6];
282    size_t size = 128;
283    char *res = NULL;
284    char buf[33];
285    unsigned int i, j;
286 
287    if (!key)
288      return;
289 
290    if (!emile_cipher_init()) return ;
291 
292    if (key->private_key)
293      {
294         if (gnutls_x509_privkey_export_rsa_raw(key->private_key,
295                                                rsa_raw + 0, /* Modulus */
296                                                rsa_raw + 1, /* Public exponent */
297                                                rsa_raw + 2, /* Private exponent */
298                                                rsa_raw + 3, /* First prime */
299                                                rsa_raw + 4, /* Second prime */
300                                                rsa_raw + 5)) /* Coefficient */
301           goto on_error;
302 
303         if (!(res = malloc(size)))
304           goto on_error;
305 
306         fprintf(out, "Private Key:\n");
307         buf[32] = '\0';
308 
309         for (i = 0; i < 6; i++)
310           {
311              while ((err = gnutls_hex_encode(rsa_raw + i, res, &size)) ==
312                     GNUTLS_E_SHORT_MEMORY_BUFFER)
313                {
314                   char *temp;
315 
316                   size += 128;
317                   if (!(temp = realloc(res, size)))
318                     goto on_error;
319                   res = temp;
320                }
321              if (err)
322                goto on_error;
323 
324              fprintf(out, "\t%s:\n", names[i]);
325              for (j = 0; strlen(res) > j; j += 32)
326                {
327                   snprintf(buf, 32, "%s", res + j);
328                   fprintf(out, "\t\t%s\n", buf);
329                }
330           }
331         free(res);
332         res = NULL;
333      }
334 
335    if (key->certificate)
336      {
337         fprintf(out, "Public certificate:\n");
338         if (gnutls_x509_crt_print(key->certificate, GNUTLS_X509_CRT_FULL,
339                                   &data))
340           goto on_error;
341 
342         fprintf(out, "%s\n", data.data);
343         gnutls_free(data.data);
344         data.data = NULL;
345      }
346 
347 on_error:
348    if (res)
349      free(res);
350 
351    if (data.data)
352      gnutls_free(data.data);
353 
354    return;
355 # else /* ifdef HAVE_GNUTLS */
356    RSA *rsa;
357    DSA *dsa;
358    DH *dh;
359 
360    if (!key)
361      return;
362 
363    if (!emile_cipher_init()) return ;
364 
365    rsa = EVP_PKEY_get1_RSA(key->private_key);
366    if (rsa)
367      {
368         fprintf(out, "Private key (RSA):\n");
369         RSA_print_fp(out, rsa, 0);
370      }
371 
372    dsa = EVP_PKEY_get1_DSA(key->private_key);
373    if (dsa)
374      {
375         fprintf(out, "Private key (DSA):\n");
376         DSA_print_fp(out, dsa, 0);
377      }
378 
379    dh = EVP_PKEY_get1_DH(key->private_key);
380    if (dh)
381      {
382         fprintf(out, "Private key (DH):\n");
383         DHparams_print_fp(out, dh);
384      }
385 
386    fprintf(out, "Public certificate:\n");
387    X509_print_fp(out, key->certificate);
388 # endif /* ifdef HAVE_GNUTLS */
389 #else /* ifdef HAVE_SIGNATURE */
390    key = NULL;
391    out = NULL;
392    ERR("You need to compile signature support in EET.");
393 #endif /* ifdef HAVE_SIGNATURE */
394 }
395 
396 void
eet_identity_ref(Eet_Key * key)397 eet_identity_ref(Eet_Key *key)
398 {
399    if (!key)
400      return;
401 
402    key->references++;
403 }
404 
405 void
eet_identity_unref(Eet_Key * key)406 eet_identity_unref(Eet_Key *key)
407 {
408    if (!key)
409      return;
410 
411    key->references--;
412    eet_identity_close(key);
413 }
414 
415 void *
eet_identity_compute_sha1(const void * data_base,unsigned int data_length,int * sha1_length)416 eet_identity_compute_sha1(const void  *data_base,
417                           unsigned int data_length,
418                           int         *sha1_length)
419 {
420    void *result;
421 
422 #ifdef HAVE_SIGNATURE
423 # ifdef HAVE_GNUTLS
424    result = malloc(gcry_md_get_algo_dlen(GCRY_MD_SHA1));
425    if (!result)
426      return NULL;
427 
428    gcry_md_hash_buffer(GCRY_MD_SHA1, result, data_base, data_length);
429    if (sha1_length)
430      *sha1_length = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
431 
432 # else /* ifdef HAVE_GNUTLS */
433 #  ifdef HAVE_OPENSSL
434    result = malloc(SHA_DIGEST_LENGTH);
435    if (!result)
436      return NULL;
437 
438    SHA1(data_base, data_length, result);
439    if (sha1_length)
440      *sha1_length = SHA_DIGEST_LENGTH;
441 
442 #  else /* ifdef HAVE_OPENSSL */
443    result = NULL;
444 #  endif /* ifdef HAVE_OPENSSL */
445 # endif /* ifdef HAVE_GNUTLS */
446 #else /* ifdef HAVE_SIGNATURE */
447    data_base = NULL;
448    data_length = 0;
449    sha1_length = NULL;
450    result = NULL;
451 #endif /* ifdef HAVE_SIGNATURE */
452 
453    return result;
454 }
455 
456 Eet_Error
eet_identity_sign(FILE * fp,Eet_Key * key)457 eet_identity_sign(FILE    *fp,
458                   Eet_Key *key)
459 {
460 #ifdef HAVE_SIGNATURE
461    Eet_Error err = EET_ERROR_NONE;
462    struct stat st_buf;
463    void *data;
464    int fd;
465    int head[3];
466    unsigned char *sign = NULL;
467    unsigned char *cert = NULL;
468 # ifdef HAVE_GNUTLS
469    gnutls_datum_t datum = { NULL, 0 };
470    size_t sign_len = 0;
471    size_t cert_len = 0;
472    gnutls_datum_t signum = { NULL, 0 };
473    gnutls_privkey_t privkey;
474 # else /* ifdef HAVE_GNUTLS */
475 #  if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
476    EVP_MD_CTX *md_ctx;
477 #  else
478    EVP_MD_CTX md_ctx;
479 #  endif
480    unsigned int sign_len = 0;
481    int cert_len = 0;
482 # endif /* ifdef HAVE_GNUTLS */
483 
484    /* A few check and flush pending write. */
485    if (!fp || !key || !key->certificate || !key->private_key)
486      return EET_ERROR_BAD_OBJECT;
487 
488    if (!emile_cipher_init()) return EET_ERROR_NOT_IMPLEMENTED;
489 
490    /* Get the file size. */
491    fd = fileno(fp);
492    if (fd < 0)
493      return EET_ERROR_BAD_OBJECT;
494 
495    if (fstat(fd, &st_buf) < 0)
496      return EET_ERROR_MMAP_FAILED;
497 
498    /* let's make mmap safe and just get 0 pages for IO erro */
499    eina_mmap_safety_enabled_set(EINA_TRUE);
500 
501    /* Map the file in memory. */
502    data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
503    if (data == MAP_FAILED)
504      return EET_ERROR_MMAP_FAILED;
505 
506 # ifdef HAVE_GNUTLS
507    datum.data = data;
508    datum.size = st_buf.st_size;
509 
510    /* Get the signature length */
511    if (gnutls_privkey_init(&privkey) < 0)
512      {
513         err = EET_ERROR_SIGNATURE_FAILED;
514         goto on_error;
515      }
516 
517    if (gnutls_privkey_import_x509(privkey, key->private_key, 0) < 0)
518      {
519         err = EET_ERROR_SIGNATURE_FAILED;
520         goto on_error;
521      }
522 
523    if (gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, &datum, &signum) < 0)
524      {
525         err = EET_ERROR_SIGNATURE_FAILED;
526         goto on_error;
527      }
528 
529    sign = signum.data;
530    sign_len = signum.size;
531 
532    /* Get the certificate length */
533    if (gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert,
534                               &cert_len) &&
535        !cert_len)
536      {
537         err = EET_ERROR_SIGNATURE_FAILED;
538         goto on_error;
539      }
540 
541    /* Get the certificate */
542    cert = malloc(cert_len);
543    if (!cert ||
544        gnutls_x509_crt_export(key->certificate, GNUTLS_X509_FMT_DER, cert,
545                               &cert_len))
546      {
547         if (!cert)
548           err = EET_ERROR_OUT_OF_MEMORY;
549         else
550           err = EET_ERROR_SIGNATURE_FAILED;
551 
552         goto on_error;
553      }
554 
555 # else /* ifdef HAVE_GNUTLS */
556    sign_len = EVP_PKEY_size(key->private_key);
557    sign = malloc(sign_len);
558    if (!sign)
559      {
560         err = EET_ERROR_OUT_OF_MEMORY;
561         goto on_error;
562      }
563 
564    /* Do the signature. */
565 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
566    md_ctx = EVP_MD_CTX_new();
567    EVP_SignInit(md_ctx, EVP_sha1());
568    EVP_SignUpdate(md_ctx, data, st_buf.st_size);
569    err = EVP_SignFinal(md_ctx,
570                        sign,
571                        (unsigned int *)&sign_len,
572                        key->private_key);
573    EVP_MD_CTX_free(md_ctx);
574 #else
575    EVP_SignInit(&md_ctx, EVP_sha1());
576    EVP_SignUpdate(&md_ctx, data, st_buf.st_size);
577    err = EVP_SignFinal(&md_ctx,
578                        sign,
579                        (unsigned int *)&sign_len,
580                        key->private_key);
581    EVP_MD_CTX_cleanup(&md_ctx);
582 #endif
583    if (err != 1)
584      {
585         ERR_print_errors_fp(stdout);
586         err = EET_ERROR_SIGNATURE_FAILED;
587         goto on_error;
588      }
589 
590    /* Give me the der (binary form for X509). */
591    cert_len = i2d_X509(key->certificate, &cert);
592    if (cert_len < 0)
593      {
594         ERR_print_errors_fp(stdout);
595         err = EET_ERROR_X509_ENCODING_FAILED;
596         goto on_error;
597      }
598 
599 # endif /* ifdef HAVE_GNUTLS */
600    /* Append the signature at the end of the file. */
601    head[0] = (int)eina_htonl ((unsigned int)EET_MAGIC_SIGN);
602    head[1] = (int)eina_htonl ((unsigned int)sign_len);
603    head[2] = (int)eina_htonl ((unsigned int)cert_len);
604 
605    if (fwrite(head, sizeof(head), 1, fp) != 1)
606      {
607         err = EET_ERROR_WRITE_ERROR;
608         goto on_error;
609      }
610 
611    if (fwrite(sign, sign_len, 1, fp) != 1)
612      {
613         err = EET_ERROR_WRITE_ERROR;
614         goto on_error;
615      }
616 
617    if (fwrite(cert, cert_len, 1, fp) != 1)
618      {
619         err = EET_ERROR_WRITE_ERROR;
620         goto on_error;
621      }
622 
623 on_error:
624 # ifdef HAVE_GNUTLS
625    if (cert)
626      free(cert);
627 
628 # else /* ifdef HAVE_GNUTLS */
629    if (cert)
630      OPENSSL_free(cert);
631 
632 # endif /* ifdef HAVE_GNUTLS */
633    if (sign)
634      free(sign);
635 
636    munmap(data, st_buf.st_size);
637    return err;
638 #else /* ifdef HAVE_SIGNATURE */
639    fp = NULL;
640    key = NULL;
641    return EET_ERROR_NOT_IMPLEMENTED;
642 #endif /* ifdef HAVE_SIGNATURE */
643 }
644 
645 const void *
eet_identity_check(const void * data_base,unsigned int data_length,void ** sha1,int * sha1_length,const void * signature_base,unsigned int signature_length,const void ** raw_signature_base,unsigned int * raw_signature_length,int * x509_length)646 eet_identity_check(const void   *data_base,
647                    unsigned int  data_length,
648                    void        **sha1,
649                    int          *sha1_length,
650                    const void   *signature_base,
651                    unsigned int  signature_length,
652                    const void  **raw_signature_base,
653                    unsigned int *raw_signature_length,
654                    int          *x509_length)
655 {
656 #ifdef HAVE_SIGNATURE
657    const int *header = signature_base;
658    const unsigned char *sign;
659    const unsigned char *cert_der;
660    int sign_len;
661    int cert_len;
662    int magic;
663 
664    /* At least the header size */
665    if (signature_length < sizeof(int) * 3)
666      return NULL;
667 
668    if (!emile_cipher_init()) return NULL;
669 
670    /* Get the header */
671    memcpy(&magic,    header, sizeof(int));
672    memcpy(&sign_len, header+1, sizeof(int));
673    memcpy(&cert_len, header+2, sizeof(int));
674 
675    magic = eina_ntohl(magic);
676    sign_len = eina_ntohl(sign_len);
677    cert_len = eina_ntohl(cert_len);
678 
679    /* Verify the header */
680    if (magic != EET_MAGIC_SIGN)
681      return NULL;
682 
683    if (sign_len + cert_len + sizeof(int) * 3 > signature_length)
684      return NULL;
685 
686    /* Update the signature and certificate pointer */
687    sign = (unsigned char *)signature_base + sizeof(int) * 3;
688    cert_der = sign + sign_len;
689 
690 # ifdef HAVE_GNUTLS
691    gnutls_x509_crt_t cert;
692    gnutls_datum_t datum;
693    gnutls_datum_t signature;
694    gnutls_pubkey_t pubkey;
695    unsigned char *hash;
696    gcry_md_hd_t md;
697    int err;
698 
699    /* Create an understanding certificate structure for gnutls */
700    datum.data = (void *)cert_der;
701    datum.size = cert_len;
702    gnutls_x509_crt_init(&cert);
703    gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER);
704 
705    signature.data = (void *)sign;
706    signature.size = sign_len;
707 
708    /* Verify the signature */
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)
721      goto on_error;
722 
723    datum.size = gcry_md_get_algo_dlen(GCRY_MD_SHA1);
724    datum.data = hash;
725 
726    if (gnutls_pubkey_init(&pubkey) < 0)
727      goto on_error;
728 
729    if (gnutls_pubkey_import_x509(pubkey, cert, 0) < 0)
730      goto on_error;
731 
732    if (gnutls_pubkey_verify_hash2(pubkey,
733                                   gnutls_x509_crt_get_signature_algorithm(cert),
734                                   0,
735                                   &datum, &signature) < 0)
736      goto on_error;
737 
738    if (sha1)
739      {
740         *sha1 = malloc(datum.size);
741         if (!*sha1) goto on_error;
742 
743         memcpy(*sha1, hash, datum.size);
744         *sha1_length = datum.size;
745      }
746 
747    gcry_md_close(md);
748    gnutls_x509_crt_deinit(cert);
749 
750 # else /* ifdef HAVE_GNUTLS */
751    const unsigned char *tmp;
752    EVP_PKEY *pkey;
753    X509 *x509;
754 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
755    EVP_MD_CTX *md_ctx;
756 #else
757    EVP_MD_CTX md_ctx;
758 #endif
759    int err;
760 
761    /* Strange but d2i_X509 seems to put 0 all over the place. */
762    tmp = alloca(cert_len);
763    memcpy((char *)tmp, cert_der, cert_len);
764    x509 = d2i_X509(NULL, &tmp, cert_len);
765    if (!x509)
766      return NULL;
767 
768    /* Get public key - eay */
769    pkey = X509_get_pubkey(x509);
770    if (!pkey)
771      {
772         X509_free(x509);
773         return NULL;
774      }
775 
776    /* Verify the signature */
777 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
778    md_ctx = EVP_MD_CTX_new();
779    EVP_VerifyInit(md_ctx, EVP_sha1());
780    EVP_VerifyUpdate(md_ctx, data_base, data_length);
781    err = EVP_VerifyFinal(md_ctx, sign, sign_len, pkey);
782    EVP_MD_CTX_free(md_ctx);
783 #else
784    EVP_VerifyInit(&md_ctx, EVP_sha1());
785    EVP_VerifyUpdate(&md_ctx, data_base, data_length);
786    err = EVP_VerifyFinal(&md_ctx, sign, sign_len, pkey);
787    EVP_MD_CTX_cleanup(&md_ctx);
788 #endif
789 
790    X509_free(x509);
791    EVP_PKEY_free(pkey);
792 
793    if (sha1)
794      {
795         *sha1 = NULL;
796         *sha1_length = -1;
797      }
798 
799    if (err != 1)
800      return NULL;
801 
802 # endif /* ifdef HAVE_GNUTLS */
803    if (x509_length)
804      *x509_length = cert_len;
805 
806    if (raw_signature_base)
807      *raw_signature_base = sign;
808 
809    if (raw_signature_length)
810      *raw_signature_length = sign_len;
811 
812    return cert_der;
813 # ifdef HAVE_GNUTLS
814  on_error:
815    gcry_md_close(md);
816    return NULL;
817 # endif
818 #else /* ifdef HAVE_SIGNATURE */
819    data_base = NULL;
820    data_length = 0;
821    sha1 = NULL;
822    sha1_length = NULL;
823    signature_base = NULL;
824    signature_length = 0;
825    raw_signature_base = NULL;
826    raw_signature_length = NULL;
827    x509_length = NULL;
828    return NULL;
829 #endif /* ifdef HAVE_SIGNATURE */
830 }
831 
832 EAPI void
eet_identity_certificate_print(const unsigned char * certificate,int der_length,FILE * out)833 eet_identity_certificate_print(const unsigned char *certificate,
834                                int                  der_length,
835                                FILE                *out)
836 {
837 #ifdef HAVE_SIGNATURE
838    if (!certificate || !out || der_length <= 0)
839      {
840         ERR("No certificate provided.");
841         return;
842      }
843 
844    if (!emile_cipher_init()) return ;
845 
846 # ifdef HAVE_GNUTLS
847    gnutls_datum_t datum;
848    gnutls_x509_crt_t cert;
849 
850    /* Create an understanding certificate structure for gnutls */
851    datum.data = (void *)certificate;
852    datum.size = der_length;
853    if (gnutls_x509_crt_init(&cert))
854      goto on_error;
855 
856    if (gnutls_x509_crt_import(cert, &datum, GNUTLS_X509_FMT_DER))
857      goto on_error;
858 
859    /* Pretty print the certificate */
860    datum.data = NULL;
861    datum.size = 0;
862    if (gnutls_x509_crt_print(cert, GNUTLS_X509_CRT_FULL, &datum))
863      goto on_error;
864 
865    INF("Public certificate :");
866    INF("%s", datum.data);
867 
868 on_error:
869    if (datum.data)
870      gnutls_free(datum.data);
871 
872    gnutls_x509_crt_deinit(cert);
873 # else /* ifdef HAVE_GNUTLS */
874    const unsigned char *tmp;
875    X509 *x509;
876 
877    /* Strange but d2i_X509 seems to put 0 all over the place. */
878    tmp = alloca(der_length);
879    memcpy((char *)tmp, certificate, der_length);
880    x509 = d2i_X509(NULL, &tmp, der_length);
881    if (!x509)
882      {
883         INF("Not a valid certificate.");
884         return;
885      }
886 
887    INF("Public certificate :");
888    X509_print_fp(out, x509);
889 
890    X509_free(x509);
891 # endif /* ifdef HAVE_GNUTLS */
892 #else /* ifdef HAVE_SIGNATURE */
893    certificate = NULL;
894    der_length = 0;
895    out = NULL;
896    ERR("You need to compile signature support in EET.");
897 #endif /* ifdef HAVE_SIGNATURE */
898 }
899 
900 Eet_Error
eet_cipher(const void * data,unsigned int size,const char * key,unsigned int length,void ** result,unsigned int * result_length)901 eet_cipher(const void   *data,
902            unsigned int  size,
903            const char   *key,
904            unsigned int  length,
905            void        **result,
906            unsigned int *result_length)
907 {
908    Eina_Binbuf *out;
909    Eina_Binbuf *in;
910 
911    in = eina_binbuf_manage_new(data, size, EINA_TRUE);
912    out = emile_binbuf_cipher(EMILE_AES256_CBC, in, key, length);
913 
914    if (result_length) *result_length = out ? eina_binbuf_length_get(out) : 0;
915    if (result) *result = out ? eina_binbuf_string_steal(out) : NULL;
916 
917    eina_binbuf_free(out);
918    eina_binbuf_free(in);
919    return out ? EET_ERROR_NONE : EET_ERROR_ENCRYPT_FAILED;
920 }
921 
922 Eet_Error
eet_decipher(const void * data,unsigned int size,const char * key,unsigned int length,void ** result,unsigned int * result_length)923 eet_decipher(const void   *data,
924              unsigned int  size,
925              const char   *key,
926              unsigned int  length,
927              void        **result,
928              unsigned int *result_length)
929 {
930    Eina_Binbuf *out;
931    Eina_Binbuf *in;
932 
933    in = eina_binbuf_manage_new(data, size, EINA_TRUE);
934    out = emile_binbuf_decipher(EMILE_AES256_CBC, in, key, length);
935 
936    if (result_length) *result_length = out ? eina_binbuf_length_get(out) : 0;
937    if (result) *result = out ? eina_binbuf_string_steal(out) : NULL;
938 
939    eina_binbuf_free(out);
940    eina_binbuf_free(in);
941    return out ? EET_ERROR_NONE : EET_ERROR_DECRYPT_FAILED;
942 }
943