@@ -2483,7 +2483,12 @@ gboolean bd_crypto_luks_reencrypt (const gchar *device, BDCryptoLUKSReencryptPar
2483
2483
paramsReencrypt .luks2 = & paramsLuks2 ;
2484
2484
2485
2485
paramsLuks2 .sector_size = params -> sector_size ;
2486
- paramsLuks2 .pbkdf = get_pbkdf_params (params -> pbkdf , error );
2486
+ if (params -> pbkdf == NULL ) {
2487
+ paramsLuks2 .pbkdf = crypt_get_pbkdf_default (CRYPT_LUKS2 );
2488
+ } else {
2489
+ paramsLuks2 .pbkdf = get_pbkdf_params (params -> pbkdf , error );
2490
+ }
2491
+
2487
2492
if (paramsLuks2 .pbkdf == NULL ) {
2488
2493
/* get info to log */
2489
2494
if (params -> pbkdf != NULL && params -> pbkdf -> type != NULL ) {
@@ -2530,6 +2535,226 @@ gboolean bd_crypto_luks_reencrypt (const gchar *device, BDCryptoLUKSReencryptPar
2530
2535
return TRUE;
2531
2536
}
2532
2537
2538
+ /**
2539
+ * bd_crypto_luks_encrypt:
2540
+ * @device: device to encrypt. Either an active device name for online encryption, or a block device for offline encryption.
2541
+ * Must match the @params's "offline" parameter
2542
+ * @params: encryption parameters
2543
+ * @context: key slot context to unlock @device. The newly created keyslot will use the same context
2544
+ * @prog_func: (scope call) (nullable): progress function. Also used to possibly stop encryption
2545
+ * @error: (out) (optional): place to store error (if any)
2546
+ *
2547
+ * Encrypts @device. In contrast to %bd_crypto_luks_format, possible existent data on @device is not destroyed,
2548
+ * but encrypted, i.e., is usable after activating device.
2549
+ *
2550
+ * Important: you need to ensure that there is enough free (unallocated) space on @device for a LUKS header (recomended 16 to 32 MiB).
2551
+ *
2552
+ * Returns: true, if the encryption was successful or gracefully stopped with @prog_func.
2553
+ * false, if an error occurred.
2554
+ *
2555
+ * Supported @context types for this function: passphrase
2556
+ *
2557
+ * Tech category: %BD_CRYPTO_TECH_LUKS-%BD_CRYPTO_TECH_MODE_MODIFY
2558
+ */
2559
+ gboolean bd_crypto_luks_encrypt (const gchar * device , BDCryptoLUKSReencryptParams * params , BDCryptoKeyslotContext * context , BDCryptoLUKSReencryptProgFunc prog_func , GError * * error ) {
2560
+ struct crypt_device * cd = NULL ;
2561
+ struct crypt_params_reencrypt paramsReencrypt = {};
2562
+ struct crypt_params_luks2 paramsLuks2 = {};
2563
+ struct reencryption_progress_struct usrptr ;
2564
+
2565
+ guint key_size = params -> key_size / 8 ; /* convert bits to bytes */
2566
+ const gchar * HEADER_FILENAME_TEMPLATE = "libblockdev-crypto-luks-encrypt-XXXXXX" ;
2567
+ gchar * header_file_path = NULL ;
2568
+ int allocated_keyslot ;
2569
+ gint ret , fd = 0 ;
2570
+ guint64 progress_id = 0 ;
2571
+ gchar * msg = NULL ;
2572
+ GError * l_error = NULL ;
2573
+
2574
+ msg = g_strdup_printf ("Started encryption of LUKS device '%s'" , device );
2575
+ progress_id = bd_utils_report_started (msg );
2576
+ g_free (msg );
2577
+
2578
+ if (context -> type != BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE ) {
2579
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_INVALID_CONTEXT ,
2580
+ "Only the 'passphrase' context type is supported for LUKS encrypt." );
2581
+ bd_utils_report_finished (progress_id , l_error -> message );
2582
+ g_propagate_error (error , l_error );
2583
+ crypt_free (cd );
2584
+ return FALSE;
2585
+ }
2586
+
2587
+ fd = g_file_open_tmp (HEADER_FILENAME_TEMPLATE , & header_file_path , & l_error );
2588
+ if (fd == -1 ) {
2589
+ g_set_error (error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_REENCRYPT_FAILED ,
2590
+ "Failed to create temporary header file: %s" , l_error -> message );
2591
+ bd_utils_report_finished (progress_id , (* error )-> message );
2592
+ g_free (header_file_path );
2593
+ crypt_free (cd );
2594
+ return FALSE;
2595
+ }
2596
+
2597
+ ret = posix_fallocate (fd , 0 , 4096 );
2598
+ close (fd );
2599
+ if (ret != 0 ) {
2600
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_REENCRYPT_FAILED ,
2601
+ "Failed to allocate enough space for temporary header file." );
2602
+ bd_utils_report_finished (progress_id , l_error -> message );
2603
+ g_propagate_error (error , l_error );
2604
+ unlink (header_file_path );
2605
+ g_free (header_file_path );
2606
+ crypt_free (cd );
2607
+ return FALSE;
2608
+ }
2609
+
2610
+ ret = crypt_init (& cd , header_file_path );
2611
+ if (ret < 0 ) {
2612
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_DEVICE ,
2613
+ "Failed to initialize device with detached header: %s" , strerror_l (- ret , c_locale ));
2614
+ bd_utils_report_finished (progress_id , l_error -> message );
2615
+ g_propagate_error (error , l_error );
2616
+ unlink (header_file_path );
2617
+ g_free (header_file_path );
2618
+ return FALSE;
2619
+ }
2620
+
2621
+ paramsLuks2 .data_device = device ;
2622
+ paramsLuks2 .sector_size = params -> sector_size ;
2623
+ paramsLuks2 .pbkdf = get_pbkdf_params (params -> pbkdf , error );
2624
+
2625
+ crypt_set_data_offset (cd , 16 MiB / SECTOR_SIZE );
2626
+ ret = crypt_format (cd , CRYPT_LUKS2 , params -> cipher , params -> cipher_mode , NULL , NULL , key_size , & paramsLuks2 );
2627
+ if (ret < 0 ) {
2628
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_REENCRYPT_FAILED ,
2629
+ "Failed to format a header file: %s" , strerror_l (- ret , c_locale ));
2630
+ bd_utils_report_finished (progress_id , l_error -> message );
2631
+ g_propagate_error (error , l_error );
2632
+ unlink (header_file_path );
2633
+ g_free (header_file_path );
2634
+ crypt_free (cd );
2635
+ return FALSE;
2636
+ }
2637
+
2638
+ ret = crypt_keyslot_add_by_key (cd ,
2639
+ CRYPT_ANY_SLOT ,
2640
+ NULL ,
2641
+ key_size ,
2642
+ (const char * ) context -> u .passphrase .pass_data ,
2643
+ context -> u .passphrase .data_len ,
2644
+ 0 );
2645
+ if (ret < 0 ) {
2646
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_ADD_KEY ,
2647
+ "Failed to add key: %s" , strerror_l (- ret , c_locale ));
2648
+ bd_utils_report_finished (progress_id , l_error -> message );
2649
+ g_propagate_error (error , l_error );
2650
+ unlink (header_file_path );
2651
+ g_free (header_file_path );
2652
+ crypt_free (cd );
2653
+ return FALSE;
2654
+ }
2655
+ allocated_keyslot = ret ;
2656
+ bd_utils_report_progress (progress_id , 10 , "Added new keyslot" );
2657
+
2658
+ paramsReencrypt .mode = CRYPT_REENCRYPT_ENCRYPT ;
2659
+ paramsReencrypt .direction = CRYPT_REENCRYPT_BACKWARD ;
2660
+ paramsReencrypt .resilience = params -> resilience ;
2661
+ paramsReencrypt .hash = params -> hash ;
2662
+ paramsReencrypt .data_shift = 16 MiB / SECTOR_SIZE ;
2663
+ paramsReencrypt .max_hotzone_size = params -> max_hotzone_size ;
2664
+ paramsReencrypt .device_size = 0 ;
2665
+ paramsReencrypt .flags = CRYPT_REENCRYPT_INITIALIZE_ONLY ;
2666
+ paramsReencrypt .flags |= CRYPT_REENCRYPT_MOVE_FIRST_SEGMENT ;
2667
+ paramsReencrypt .luks2 = & paramsLuks2 ;
2668
+
2669
+ /* Initialize reencryption */
2670
+ ret = crypt_reencrypt_init_by_passphrase (cd ,
2671
+ params -> offline ? NULL : device ,
2672
+ (const char * ) context -> u .passphrase .pass_data ,
2673
+ context -> u .passphrase .data_len ,
2674
+ CRYPT_ANY_SLOT ,
2675
+ allocated_keyslot ,
2676
+ params -> cipher ,
2677
+ params -> cipher_mode ,
2678
+ & paramsReencrypt );
2679
+ if (ret < 0 ) {
2680
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_REENCRYPT_FAILED ,
2681
+ "Failed to initialize encryption: %s" , strerror_l (- ret , c_locale ));
2682
+ bd_utils_report_finished (progress_id , l_error -> message );
2683
+ g_propagate_error (error , l_error );
2684
+ unlink (header_file_path );
2685
+ g_free (header_file_path );
2686
+ crypt_free (cd );
2687
+ return FALSE;
2688
+ }
2689
+
2690
+ /* Set header from temporary file to disk */
2691
+ /* 1/2: Re-init without detached header */
2692
+ crypt_free (cd );
2693
+ cd = NULL ;
2694
+ ret = crypt_init (& cd , device );
2695
+ if (ret < 0 ) {
2696
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_DEVICE ,
2697
+ "Failed to re-initialize device: %s" , strerror_l (- ret , c_locale ));
2698
+ bd_utils_report_finished (progress_id , l_error -> message );
2699
+ g_propagate_error (error , l_error );
2700
+ unlink (header_file_path );
2701
+ g_free (header_file_path );
2702
+ return FALSE;
2703
+ }
2704
+
2705
+ /* 2/2: Set header */
2706
+ ret = crypt_header_restore (cd , CRYPT_LUKS2 , header_file_path );
2707
+ unlink (header_file_path );
2708
+ g_free (header_file_path );
2709
+ if (ret < 0 ) {
2710
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_DEVICE ,
2711
+ "Failed to re-initialize device: %s" , strerror_l (- ret , c_locale ));
2712
+ bd_utils_report_finished (progress_id , l_error -> message );
2713
+ g_propagate_error (error , l_error );
2714
+ crypt_free (cd );
2715
+ return FALSE;
2716
+ }
2717
+
2718
+ paramsReencrypt .flags &= ~CRYPT_REENCRYPT_INITIALIZE_ONLY ;
2719
+ paramsReencrypt .flags |= CRYPT_REENCRYPT_RESUME_ONLY ;
2720
+
2721
+ ret = crypt_reencrypt_init_by_passphrase (cd ,
2722
+ params -> offline ? NULL : device ,
2723
+ (const char * ) context -> u .passphrase .pass_data ,
2724
+ context -> u .passphrase .data_len ,
2725
+ CRYPT_ANY_SLOT ,
2726
+ allocated_keyslot ,
2727
+ params -> cipher ,
2728
+ params -> cipher_mode ,
2729
+ & paramsReencrypt );
2730
+ if (ret < 0 ) {
2731
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_REENCRYPT_FAILED ,
2732
+ "Failed to re-initialize encryption: %s" , strerror_l (- ret , c_locale ));
2733
+ bd_utils_report_finished (progress_id , l_error -> message );
2734
+ g_propagate_error (error , l_error );
2735
+ crypt_free (cd );
2736
+ return FALSE;
2737
+ }
2738
+
2739
+ /* marshal to usrptr */
2740
+ usrptr .progress_id = progress_id ;
2741
+ usrptr .usr_func = prog_func ;
2742
+
2743
+ ret = crypt_reencrypt_run (cd , reencryption_progress , & usrptr );
2744
+ if (ret != 0 ) {
2745
+ g_set_error (& l_error , BD_CRYPTO_ERROR , BD_CRYPTO_ERROR_REENCRYPT_FAILED ,
2746
+ "Reencryption failed: %s" , strerror_l (- ret , c_locale ));
2747
+ bd_utils_report_finished (progress_id , l_error -> message );
2748
+ g_propagate_error (error , l_error );
2749
+ crypt_free (cd );
2750
+ return FALSE;
2751
+ }
2752
+
2753
+ crypt_free (cd );
2754
+ bd_utils_report_finished (progress_id , "Completed." );
2755
+ return TRUE;
2756
+ }
2757
+
2533
2758
/**
2534
2759
* bd_crypto_luks_reencrypt_status:
2535
2760
* @device: an active device name or a block device
0 commit comments