summaryrefslogtreecommitdiff
path: root/libsylph/ssl.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-27 21:52:12 +0100
committerSimeon Simeonov2018-02-27 21:52:12 +0100
commit1bb2a9d33e8cd193c21f9995fb7852c7562cafcf (patch)
treebf54cba95a7b7afa68b33f8cb40b53d351b880ff /libsylph/ssl.c
parent3f7a3add4dc0814e01c3032d73a4cdd29372f8d4 (diff)
First prototype
Diffstat (limited to 'libsylph/ssl.c')
-rw-r--r--libsylph/ssl.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/libsylph/ssl.c b/libsylph/ssl.c
index 8413925..5a76b8b 100644
--- a/libsylph/ssl.c
+++ b/libsylph/ssl.c
@@ -32,6 +32,11 @@
32#include "ssl.h" 32#include "ssl.h"
33#include "ssl_hostname_validation.h" 33#include "ssl_hostname_validation.h"
34 34
35#define SALT_SIZE 16
36#define CIPHER EVP_aes_256_cfb()
37#define KEY_HASH EVP_sha256()
38#define DIGEST_HASH EVP_sha256()
39
35static SSL_CTX *ssl_ctx_SSLv23 = NULL; 40static SSL_CTX *ssl_ctx_SSLv23 = NULL;
36static SSL_CTX *ssl_ctx_TLSv1 = NULL; 41static SSL_CTX *ssl_ctx_TLSv1 = NULL;
37 42
@@ -402,4 +407,376 @@ void ssl_set_verify_func(SSLVerifyFunc func)
402 verify_ui_func = func; 407 verify_ui_func = func;
403} 408}
404 409
410/* master password related functions */
411static gint secure_derive_key(guchar *key,
412 gint length_key,
413 const gchar *passphrase,
414 const guchar *salt) {
415
416 guint length_buffer, length_hash;
417 guchar *buffer, *ptr_hash;
418
419 EVP_MD_CTX *mdctx;
420
421 OPENSSL_cleanse(key, length_key);
422
423 length_buffer = SALT_SIZE + strlen(passphrase);
424 buffer = OPENSSL_malloc(length_buffer);
425 OPENSSL_cleanse(buffer, length_buffer);
426
427 memcpy(buffer, salt, SALT_SIZE);
428 memcpy(buffer + SALT_SIZE, passphrase, strlen(passphrase));
429
430 mdctx = EVP_MD_CTX_create();
431 EVP_DigestInit_ex(mdctx, KEY_HASH, NULL);
432 EVP_DigestUpdate(mdctx, buffer, length_buffer);
433 OPENSSL_cleanse(buffer, length_buffer);
434
435 ptr_hash = OPENSSL_malloc(EVP_MD_size(KEY_HASH));
436 EVP_DigestFinal_ex(mdctx, ptr_hash, &length_hash);
437
438 memcpy(key,
439 ptr_hash,
440 (length_hash > length_key) ? length_key : length_hash);
441
442 OPENSSL_cleanse(ptr_hash, length_hash);
443 OPENSSL_free(ptr_hash);
444 OPENSSL_free(buffer);
445 EVP_MD_CTX_destroy(mdctx);
446
447 return RC_OK;
448
449}
450
451
452gint encrypt_data(gchar **encrypted,
453 gint *length_encrypted,
454 const gchar *data,
455 const gchar *passphrase,
456 gint length_data,
457 guint min_data_length,
458 gboolean rnd_salt) {
459
460 gint crypt_buffer_cnt, rc;
461 guint key_size, length_hash;
462 guint length_cleartext, length_ciphertext, length_total;
463 guchar salt[SALT_SIZE];
464 guchar *ciphertext_buffer, *total_buffer;
465 /* sensitive buffers and counters */
466 guint length_data_payload, length_padding;
467 gchar str_data_size[3];
468 guchar *data_payload_buffer, *hash_buffer, *padding_buffer, *key;
469 guchar *cleartext_buffer;
470
471 EVP_CIPHER_CTX *ctx;
472 EVP_MD_CTX *mdctx;
473
474 rc = RC_ERROR;
475
476 if (length_data < 1) {
477 return -1;
478 }
479 if (rnd_salt) {
480 if (RAND_bytes(salt, SALT_SIZE) != 1) {
481 debug_print("Random problems...\n");
482 goto cleanup;
483 }
484 } else {
485 strncpy((gchar *)salt, "FOR TESTING ONLY", SALT_SIZE);
486 }
487
488 key_size = EVP_CIPHER_key_length(CIPHER);
489 key = OPENSSL_malloc(key_size);
490 OPENSSL_cleanse(key, key_size);
491 if (secure_derive_key(key,
492 key_size,
493 passphrase,
494 salt) != RC_OK) {
495 OPENSSL_cleanse(key, key_size);
496 debug_print("Could not generate secure key\n");
497 goto cleanup;
498 }
499
500 /* prepare the data-buffer */
501 length_padding = 0;
502 if (length_data < min_data_length) {
503 g_snprintf(str_data_size, 3, "%02d", length_data);
504 length_padding = min_data_length - length_data;
505 padding_buffer = OPENSSL_malloc(length_padding);
506 OPENSSL_cleanse(padding_buffer, length_padding);
507 if (RAND_bytes(padding_buffer, length_padding) != 1) {
508 debug_print("Random problems...\n");
509 goto cleanup;
510 }
511 } else {
512 g_snprintf(str_data_size, 3, "-1");
513 }
514
515 length_data_payload = 2 + length_data + length_padding;
516 data_payload_buffer = OPENSSL_malloc(length_data_payload);
517 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
518
519 memcpy(data_payload_buffer, str_data_size, 2);
520 memcpy(data_payload_buffer + 2, data, length_data);
521 if (length_padding > 0) {
522 memcpy(data_payload_buffer + (2 + length_data),
523 padding_buffer,
524 length_padding);
525 }
526
527 mdctx = EVP_MD_CTX_create();
528 EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL);
529 EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload);
530
531 length_hash = EVP_MD_size(DIGEST_HASH);
532 hash_buffer = OPENSSL_malloc(length_hash);
533 OPENSSL_cleanse(hash_buffer, length_hash);
534 EVP_DigestFinal_ex(mdctx, hash_buffer, NULL);
535
536 length_cleartext = length_hash + length_data_payload;
537
538 cleartext_buffer = OPENSSL_malloc(length_cleartext);
539 OPENSSL_cleanse(cleartext_buffer, length_cleartext);
540
541 /* assemble cleartext-buffer */
542 memcpy(cleartext_buffer, hash_buffer, length_hash);
543 memcpy(cleartext_buffer + length_hash,
544 data_payload_buffer,
545 length_data_payload);
546 OPENSSL_cleanse(data_payload_buffer, length_data_payload); /* sensitive */
547
548 /* encryption */
549 if (!(ctx = EVP_CIPHER_CTX_new())) {
550 debug_print("New ctx failed\n");
551 goto cleanup;
552 }
553
554 length_ciphertext = 0;
555 if (EVP_EncryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) {
556 debug_print("EVP_EncryptInit_ex failed\n");
557 goto cleanup;
558 }
559
560 ciphertext_buffer = OPENSSL_malloc(length_cleartext);
561
562 crypt_buffer_cnt = 0;
563 while(1) {
564 if (EVP_EncryptUpdate(ctx,
565 ciphertext_buffer + length_ciphertext,
566 &crypt_buffer_cnt,
567 cleartext_buffer + length_ciphertext,
568 1) != 1) { /* one byte at a time */
569 debug_print("EVP_EncryptUpdate failed\n");
570 goto cleanup;
571 }
572
573 if (crypt_buffer_cnt != 1) { /* paranoia */
574 debug_print("The sizes of enc and dec text do not correspond\n");
575 goto cleanup;
576 }
577
578 ++length_ciphertext;
579
580 if (length_ciphertext >= length_cleartext) {
581 break;
582 }
583 }
584 /* No padding required for the CFB mode */
585
586 OPENSSL_cleanse(cleartext_buffer, length_cleartext); /* sensitive */
587 length_total = SALT_SIZE + length_ciphertext;
588 total_buffer = OPENSSL_malloc(length_total);
589
590 memcpy(total_buffer, salt, SALT_SIZE);
591 memcpy(total_buffer + SALT_SIZE, ciphertext_buffer, length_ciphertext);
592
593 *encrypted = g_base64_encode(total_buffer, length_total);
594 *length_encrypted = strlen(*encrypted);
595
596 rc = RC_OK;
597
598cleanup:
599 /* key */
600 OPENSSL_cleanse(key, key_size);
601 OPENSSL_free(key);
602 /* cleartext buffer */
603 OPENSSL_cleanse(cleartext_buffer, length_cleartext);
604 OPENSSL_free(cleartext_buffer);
605 /* payload buffer */
606 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
607 OPENSSL_free(data_payload_buffer);
608 /* hash */
609 OPENSSL_cleanse(hash_buffer, length_hash);
610 OPENSSL_free(hash_buffer);
611 /* padding */
612 if (length_padding > 0) {
613 OPENSSL_cleanse(padding_buffer, length_padding);
614 OPENSSL_free(padding_buffer);
615 }
616
617 OPENSSL_cleanse(str_data_size, 3); /* paranoia */
618
619 /* ciphertext buffer */
620 OPENSSL_free(ciphertext_buffer);
621
622 /* total buffer */
623 OPENSSL_free(total_buffer);
624
625 length_data_payload = 0;
626 length_padding = 0;
627
628 EVP_CIPHER_CTX_free(ctx);
629 EVP_MD_CTX_destroy(mdctx);
630
631 return rc;
632
633}
634
635
636gint decrypt_data(gchar **decrypted,
637 const gchar *data,
638 const gchar *passphrase,
639 gint length_data) {
640
641 gint rc; /* return code */
642 gint decrypt_buffer_cnt, length_ciphertext, length_decrypted;
643 guint key_size, length_hash, length_cleartext;
644 gsize length_total;
645 guchar salt[SALT_SIZE];
646 guchar *ciphertext_buffer, *total_buffer;
647 /* sensitive buffers and counters */
648 gint data_size;
649 guint length_data_payload;
650 gchar str_data_size[3];
651 guchar *data_payload_buffer, *hash_buffer, *key;
652 guchar *cleartext_buffer;
653
654 EVP_CIPHER_CTX *ctx;
655 EVP_MD_CTX *mdctx;
656
657 rc = -1;
658
659 if (length_data < 1) {
660 return -1;
661 }
662
663 total_buffer = g_base64_decode(data, &length_total);
664 length_ciphertext = length_total - SALT_SIZE;
665 ciphertext_buffer = OPENSSL_malloc(length_ciphertext);
666 OPENSSL_cleanse(ciphertext_buffer, length_ciphertext);
667
668 memcpy(salt, total_buffer, SALT_SIZE);
669 memcpy(ciphertext_buffer, total_buffer + SALT_SIZE, length_ciphertext);
670
671 key_size = EVP_CIPHER_key_length(CIPHER);
672
673 /* decryption */
674 if(!(ctx = EVP_CIPHER_CTX_new())) {
675 debug_print("New ctx failed\n");
676 goto cleanup;
677 }
678
679 key = OPENSSL_malloc(key_size);
680 OPENSSL_cleanse(key, key_size);
681 if (secure_derive_key(key,
682 key_size,
683 passphrase,
684 salt) != 0) {
685 OPENSSL_cleanse(key, key_size);
686 debug_print("Could not generate secure key\n");
687 goto cleanup;
688 }
689
690 if (EVP_DecryptInit_ex(ctx, CIPHER, NULL, key, salt) != 1) {
691 debug_print("EVP_DecryptInit_ex failed\n");
692 goto cleanup;
693 }
694 OPENSSL_cleanse(key, key_size); /* highly sensitive */
695 cleartext_buffer = OPENSSL_malloc(length_ciphertext);
696 OPENSSL_cleanse(cleartext_buffer, length_ciphertext);
697
698 length_cleartext = 0;
699 decrypt_buffer_cnt = 0;
700
701 while(1) {
702 if (EVP_DecryptUpdate(ctx,
703 cleartext_buffer + length_cleartext,
704 &decrypt_buffer_cnt,
705 ciphertext_buffer + length_cleartext,
706 1) != 1) { /* one byte at a time */
707 debug_print("EVP_EncryptUpdate failed\n");
708 goto cleanup;
709 }
710
711 if (decrypt_buffer_cnt != 1) { /* paranoia */
712 debug_print("The sizes of enc and dec text do not correspond");
713 goto cleanup;
714 }
715
716 ++length_cleartext;
717
718 if (length_cleartext >= length_ciphertext) {
719 break;
720 }
721 }
722
723
724 length_hash = EVP_MD_size(DIGEST_HASH);
725 hash_buffer = OPENSSL_malloc(length_hash);
726 length_data_payload = length_cleartext - length_hash;
727 data_payload_buffer = OPENSSL_malloc(length_data_payload);
728 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
729
730 memcpy(data_payload_buffer,
731 cleartext_buffer + length_hash,
732 length_data_payload);
733
734 mdctx = EVP_MD_CTX_create();
735 EVP_DigestInit_ex(mdctx, DIGEST_HASH, NULL);
736 EVP_DigestUpdate(mdctx, data_payload_buffer, length_data_payload);
737 EVP_DigestFinal_ex(mdctx, hash_buffer, &length_hash);
738
739 if (strncmp((const gchar*) hash_buffer,
740 (const gchar*) cleartext_buffer,
741 length_hash) != 0) {
742 debug_print("Invalid hash\n");
743 rc = RC_WRONG_HASH_OR_KEY;
744 goto cleanup;
745 }
746
747 memcpy(str_data_size, cleartext_buffer + length_hash, 2);
748 data_size = atoi(str_data_size);
749
750 if (data_size < 0) {
751 length_decrypted = length_data_payload - 2;
752 } else {
753 length_decrypted = data_size;
754 }
755 *decrypted = OPENSSL_malloc(length_decrypted);
756 memcpy(*decrypted, data_payload_buffer + 2, length_decrypted);
757
758 rc = RC_OK;
759
760cleanup:
761
762 /* key */
763 OPENSSL_cleanse(key, key_size);
764 OPENSSL_free(key);
765 /* payload buffer */
766 OPENSSL_cleanse(data_payload_buffer, length_data_payload);
767 OPENSSL_free(data_payload_buffer);
768 /* hash */
769 OPENSSL_cleanse(hash_buffer, length_hash);
770 OPENSSL_free(hash_buffer);
771 /* ciphertext */
772 OPENSSL_free(ciphertext_buffer);
773 OPENSSL_free(total_buffer);
774
775 EVP_CIPHER_CTX_free(ctx);
776 EVP_MD_CTX_destroy(mdctx);
777
778 return rc;
779
780}
781
405#endif /* USE_SSL */ 782#endif /* USE_SSL */