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