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