ZFS passphrase support
This commit is contained in:
		
							parent
							
								
									f003a8c5e7
								
							
						
					
					
						commit
						ed746949af
					
				
					 4 changed files with 91 additions and 35 deletions
				
			
		|  | @ -205,7 +205,8 @@ grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, | |||
| 				const grub_uint32_t *expected_mac, | ||||
| 				grub_zfs_endian_t endian) = NULL; | ||||
| grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key, | ||||
| 						  grub_size_t keysize) = NULL; | ||||
| 						  grub_size_t keysize, | ||||
| 						  grub_uint64_t salt) = NULL; | ||||
| 
 | ||||
| static grub_err_t  | ||||
| zlib_decompress (void *s, void *d, | ||||
|  | @ -1500,7 +1501,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, | |||
|   if (encrypted) | ||||
|     { | ||||
|       if (!grub_zfs_decrypt) | ||||
| 	err = grub_error (GRUB_ERR_BAD_FS, "zfscrypto module not loaded"); | ||||
| 	err = grub_error (GRUB_ERR_BAD_FS, "zfscrypt module not loaded"); | ||||
|       else | ||||
| 	err = grub_zfs_decrypt (data->subvol.cipher, &(bp)->blk_dva[encrypted], | ||||
| 				compbuf, psize, ((grub_uint32_t *) &zc + 5), | ||||
|  | @ -2657,8 +2658,10 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, | |||
|   const char *ptr_at, *filename; | ||||
|   grub_uint64_t headobj; | ||||
|   grub_uint64_t keychainobj; | ||||
|   grub_uint64_t salt; | ||||
|   grub_err_t err; | ||||
| 
 | ||||
| 
 | ||||
|   auto int NESTED_FUNC_ATTR iterate_zap_key (const char *name, | ||||
| 					     const void *val_in, | ||||
| 					     grub_size_t nelem, | ||||
|  | @ -2675,7 +2678,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, | |||
| 	return 0; | ||||
|       } | ||||
| 
 | ||||
|     subvol->cipher = grub_zfs_load_key (val_in, nelem); | ||||
|     subvol->cipher = grub_zfs_load_key (val_in, nelem, salt); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|  | @ -2745,7 +2748,32 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, | |||
|   keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); | ||||
|   if (grub_zfs_load_key && keychainobj) | ||||
|     { | ||||
|       dnode_end_t keychain_dn; | ||||
|       dnode_end_t keychain_dn, props_dn; | ||||
|       grub_uint64_t propsobj; | ||||
|       propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian); | ||||
| 
 | ||||
|       err = dnode_get (&(data->mos), propsobj, DMU_OT_DSL_PROPS, | ||||
| 		       &props_dn, data); | ||||
|       if (err) | ||||
| 	{ | ||||
| 	  grub_free (fsname); | ||||
| 	  grub_free (snapname); | ||||
| 	  return err; | ||||
| 	} | ||||
| 
 | ||||
|       err = zap_lookup (&props_dn, "salt", &salt, data, 0); | ||||
|       if (err == GRUB_ERR_FILE_NOT_FOUND) | ||||
| 	{ | ||||
| 	  err = 0; | ||||
| 	  grub_errno = 0; | ||||
| 	  salt = 0; | ||||
| 	} | ||||
|       if (err) | ||||
| 	{ | ||||
| 	  grub_dprintf ("zfs", "failed here\n"); | ||||
| 	  return err; | ||||
| 	} | ||||
| 
 | ||||
|       err = dnode_get (&(data->mos), keychainobj, DMU_OT_DSL_KEYCHAIN, | ||||
| 		       &keychain_dn, data); | ||||
|       if (err) | ||||
|  |  | |||
|  | @ -64,19 +64,27 @@ struct grub_zfs_key | |||
| struct grub_zfs_wrap_key | ||||
| { | ||||
|   struct grub_zfs_wrap_key *next; | ||||
|   grub_uint64_t key[GRUB_ZFS_MAX_KEYLEN / 8]; | ||||
|   grub_size_t keylen; | ||||
|   int is_passphrase; | ||||
|   grub_uint64_t key[0]; | ||||
| }; | ||||
| 
 | ||||
| static struct grub_zfs_wrap_key *zfs_wrap_keys; | ||||
| 
 | ||||
| grub_err_t | ||||
| grub_zfs_add_key (grub_uint8_t *key_in) | ||||
| grub_zfs_add_key (grub_uint8_t *key_in, | ||||
| 		  grub_size_t keylen, | ||||
| 		  int passphrase) | ||||
| { | ||||
|   struct grub_zfs_wrap_key *key; | ||||
|   key = grub_malloc (sizeof (*key)); | ||||
|   if (!passphrase && keylen > 32) | ||||
|     keylen = 32; | ||||
|   key = grub_malloc (sizeof (*key) + keylen); | ||||
|   if (!key) | ||||
|     return grub_errno; | ||||
|   grub_memcpy (key->key, key_in, GRUB_ZFS_MAX_KEYLEN); | ||||
|   key->is_passphrase = passphrase; | ||||
|   key->keylen = keylen; | ||||
|   grub_memcpy (key->key, key_in, keylen); | ||||
|   key->next = zfs_wrap_keys; | ||||
|   zfs_wrap_keys = key; | ||||
|   return GRUB_ERR_NONE; | ||||
|  | @ -168,7 +176,8 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, void *nonce, | |||
| 
 | ||||
| static grub_crypto_cipher_handle_t | ||||
| grub_zfs_load_key_real (const struct grub_zfs_key *key, | ||||
| 			grub_size_t keysize) | ||||
| 			grub_size_t keysize, | ||||
| 			grub_uint64_t salt) | ||||
| { | ||||
|   unsigned keylen; | ||||
|   struct grub_zfs_wrap_key *wrap_key; | ||||
|  | @ -192,15 +201,25 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, | |||
|   for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next) | ||||
|     { | ||||
|       grub_crypto_cipher_handle_t cipher; | ||||
|       grub_uint8_t decrypted[32], mac[32]; | ||||
|       grub_uint8_t decrypted[32], mac[32], wrap_key_real[32]; | ||||
|       cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES); | ||||
|       if (!cipher) | ||||
| 	{ | ||||
| 	  grub_errno = GRUB_ERR_NONE; | ||||
| 	  return 0; | ||||
| 	} | ||||
|       err = grub_crypto_cipher_set_key (cipher, | ||||
| 					(const grub_uint8_t *) wrap_key->key, | ||||
|       grub_memset (wrap_key_real, 0, sizeof (wrap_key_real)); | ||||
|       if (!wrap_key->is_passphrase) | ||||
| 	grub_memcpy(wrap_key_real, wrap_key->key, | ||||
| 		    wrap_key->keylen < keylen ? wrap_key->keylen : keylen); | ||||
|       else | ||||
| 	grub_crypto_pbkdf2 (GRUB_MD_SHA1, | ||||
| 			    (const grub_uint8_t *) wrap_key->key, | ||||
| 			    wrap_key->keylen, | ||||
| 			    (const grub_uint8_t *) &salt, sizeof (salt), | ||||
| 			    1000, wrap_key_real, keylen); | ||||
| 		     | ||||
|       err = grub_crypto_cipher_set_key (cipher, wrap_key_real, | ||||
| 					keylen); | ||||
|       if (err) | ||||
| 	{ | ||||
|  | @ -268,25 +287,19 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) | |||
|       if (real_size < 0) | ||||
| 	return grub_errno; | ||||
|     } | ||||
|   if (ctxt->state[0].set | ||||
|       || (argc > 0 && !ctxt->state[1].set && !ctxt->state[2].set)) | ||||
|   else | ||||
|     { | ||||
|       grub_err_t err; | ||||
|       if (real_size < GRUB_ZFS_MAX_KEYLEN) | ||||
| 	grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size); | ||||
|       err = grub_zfs_add_key (buf); | ||||
|       if (err) | ||||
| 	return err; | ||||
|       return GRUB_ERR_NONE; | ||||
|       grub_printf ("Enter ZFS password: "); | ||||
|       if (!grub_password_get ((char *) buf, 1023)) | ||||
| 	return grub_errno; | ||||
|       real_size = grub_strlen ((char *) buf); | ||||
|     } | ||||
| 
 | ||||
|   if (ctxt->state[1].set) | ||||
|     { | ||||
|       int i; | ||||
|       grub_err_t err; | ||||
|       if (real_size < 2 * GRUB_ZFS_MAX_KEYLEN) | ||||
| 	grub_memset (buf + real_size, '0', 2 * GRUB_ZFS_MAX_KEYLEN - real_size); | ||||
|       for (i = 0; i < GRUB_ZFS_MAX_KEYLEN; i++) | ||||
|       for (i = 0; i < real_size / 2; i++) | ||||
| 	{ | ||||
| 	  char c1 = grub_tolower (buf[2 * i]) - '0'; | ||||
| 	  char c2 = grub_tolower (buf[2 * i + 1]) - '0'; | ||||
|  | @ -296,12 +309,16 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) | |||
| 	    c2 += '0' - 'a' + 10; | ||||
| 	  buf[i] = (c1 << 4) | c2; | ||||
| 	} | ||||
|       err = grub_zfs_add_key (buf); | ||||
|       err = grub_zfs_add_key (buf, real_size / 2, 0); | ||||
|       if (err) | ||||
| 	return err; | ||||
|       return GRUB_ERR_NONE; | ||||
|     } | ||||
|   return GRUB_ERR_NONE; | ||||
| 
 | ||||
|   return grub_zfs_add_key (buf, real_size, | ||||
| 			   ctxt->state[2].set | ||||
| 			   || (argc == 0 && !ctxt->state[0].set | ||||
| 			       && !ctxt->state[1].set)); | ||||
| } | ||||
| 
 | ||||
| static grub_extcmd_t cmd_key; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue