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