Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

secboot: add argon2 out-of-process kdf support #15073

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

ZeyadYasser
Copy link
Contributor

MaybeRunArgon2OutOfProcessRequestHandler is supposed to be called from the main() of binaries involved with sealing/unsealing of keys (i.e. snapd and snap-bootstrap).

This switches the binary to a special mode where it acts as an argon2 out-of-process helper command, and exits when its work is done.

For more context, check docs for sb.WaitForAndRunArgon2OutOfProcessRequest and sb.NewOutOfProcessArgon2KDF for details on how the flow works in secboot.

This PR also reverts workaround from #15058 as now the argon2 kdf variants are working.

@ZeyadYasser ZeyadYasser added the Needs Samuele review Needs a review from Samuele before it can land label Feb 13, 2025
@ZeyadYasser ZeyadYasser added this to the 2.68.1 milestone Feb 13, 2025
@ZeyadYasser ZeyadYasser force-pushed the fde-argon2-out-of-process-kdf branch from 9b854ca to 4d9e5c0 Compare February 13, 2025 14:59
Copy link

github-actions bot commented Feb 13, 2025

Fri Feb 14 15:18:15 UTC 2025
The following results are from: https://github.com/canonical/snapd/actions/runs/13329597963

Failures:

Executing:

  • google-core:ubuntu-core-20-64:tests/core/gadget-update-pc
  • google:ubuntu-24.10-64:tests/main/cloud-init
  • google:ubuntu-24.04-64:tests/main/progress

Restoring:

  • google-core:ubuntu-core-20-64:tests/core/gadget-update-pc
  • google-core:ubuntu-core-20-64:tests/core/
  • google-core:ubuntu-core-20-64

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple initial comments

@@ -40,6 +41,11 @@ such as initramfs.
)

func main() {
if err := secboot.MaybeRunArgon2OutOfProcessRequestHandler(); err != nil {
fmt.Fprintf(os.Stderr, "cannot run argon2 out-of-process helper command: %v", err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a bit unclear to me why we don't want to deal with this inside the helper directly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, updated!

@@ -57,6 +58,11 @@ func main() {
snapdtool.ExecInSnapdOrCoreSnap()
}

if err := secboot.MaybeRunArgon2OutOfProcessRequestHandler(); err != nil {
fmt.Fprintf(os.Stderr, "cannot run argon2 out-of-process helper command: %v", err)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

}

const outOfProcessArgon2KDFTimeout = 100 * time.Millisecond
const argon2Cmd = "run-argon2"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my preference is something like an option "--argon2-proc"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have strong opinions on this, I went with a sub-command to be ready in case we want to pass args in the future to customize how the out-of-process helper is configured, but since this will be internal and be self invoking we can easily switch later if need arise and not worry about the binaries being in sync.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched to --argon2-proc

@ZeyadYasser ZeyadYasser requested a review from pedronis February 14, 2025 09:34
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question related to what happens if a binary uses argon2 but is not set up to process --argon2-proc ?

secboot/argon2_out_of_process_sb.go Show resolved Hide resolved
Copy link

codecov bot commented Feb 14, 2025

Codecov Report

Attention: Patch coverage is 75.00000% with 11 lines in your changes missing coverage. Please review.

Please upload report for BASE (master@cccee5f). Learn more about missing BASE report.
Report is 219 commits behind head on master.

Files with missing lines Patch % Lines
secboot/argon2_out_of_process_sb.go 85.18% 3 Missing and 1 partial ⚠️
secboot/argon2_out_of_process_dummy.go 0.00% 3 Missing ⚠️
cmd/snap-bootstrap/main.go 0.00% 2 Missing ⚠️
cmd/snapd/main.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master   #15073   +/-   ##
=========================================
  Coverage          ?   78.06%           
=========================================
  Files             ?     1183           
  Lines             ?   157779           
  Branches          ?        0           
=========================================
  Hits              ?   123174           
  Misses            ?    26956           
  Partials          ?     7649           
Flag Coverage Δ
unittests 78.06% <75.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

)

func init() {
setArgon2KDF()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will now affect every program in which one of the packages imports secboot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switched to setting the kdf implementation from MaybeRunArgon2OutOfProcessRequestHandler itself as described here #15073 (comment)


package secboot

func MaybeRunArgon2OutOfProcessRequestHandler() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should raise an error/panic if it observes a trigger for out of process secboot runner

// and sb.NewOutOfProcessArgon2KDF for details on how the flow works
// in secboot.
func MaybeRunArgon2OutOfProcessRequestHandler() {
if len(os.Args) < 2 || os.Args[1] != outOfProcessArgon2Arg {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm bit uncomfortable that this hijacks command line arguments and adds an argument which not exposed anywhere but the secboot package.

// For more context, check docs for sb.WaitForAndRunArgon2OutOfProcessRequest
// and sb.NewOutOfProcessArgon2KDF for details on how the flow works
// in secboot.
func MaybeRunArgon2OutOfProcessRequestHandler() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we change the API a little such that it can be used like so, in snapd:

// snapd/main.go

func executeSecbootArgon2Runner {
	logger.Noticef("running argon2 out-of-process helper")
	// Ignore the lock release callback and use implicit release on process termination.
	_, err := secboot.ExecuteAsArgon2Runner(secboot.Argon2RunnerOptions{
		Watchdog: false,
	})
	if err != nil {
		logger.Errorf("cannot execute runner: %v", err)
		os.Exit(1)
	}
	os.Exit(0)
}

func main() {
	...
	InstallSecbootHandlerOnArg([]string{"--secboot-argon2-runner"})
	
	if len(os.Args) == 2 && os.Args[1] == "--secboot-argon2-runner" {
		executeArgon2Runner()
		// not-reached
	}
	...
}

and snap-bootstrap:

// snap-boostrap/main.go

func main() {
	...
	InstallSecbootHandlerOnArg([]string{"secboot-argon2-runner"})
}

// snap-boostrap/cmd_secboot_argon2_runner.go

func init() {
	addCommandBuilder(func(parser *flags.Parser) {
		cmd, err := parser.AddCommand("secboot2_argon2-runner", short, long, &cmdArgon2Runner{})
		if  err != nil {
			panic(err)
		}
		// make it hidden
		cmd.Hidden = true
	})
}

type cmdArgon2Runner struct {}

func (c *cmdArgon2Runner) Execute([]string) error {
	logger.Noticef("running argon2 out-of-process helper")
	// Ignore the lock release callback and use implicit release on process termination.
	_, err := secboot.ExecuteAsArgon2Runner(secboot.Argon2RunnerOptions{
		Watchdog: false,
	})
	return err
}

Copy link
Collaborator

@pedronis pedronis Feb 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a lot of extra code that I'm not keen on. Maybe the compromise is to pass the marker flag to the MaybeRunArgon2OutOfProcessRequestHandler


package secboot

func MaybeRunArgon2OutOfProcessRequestHandler() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func MaybeRunArgon2OutOfProcessRequestHandler() {}
func MaybeRunArgon2OutOfProcessRequestHandler() {
if !isOutOfProcessArgon2KDFMode() {
panic("internal error: unexpected call to execute as argon2 runner in non-secboot binary")
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should panic when isOutOfProcessArgon2KDFMode is true

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, my bad, I copied directly without changing it

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, couple small comments

@@ -40,6 +41,8 @@ such as initramfs.
)

func main() {
secboot.HijackAndRunArgon2OutOfProcessHandlerOnArg([]string{"--argon2-proc"})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that is passed in now, I'm not against dropping "--" here


var _ = Suite(&argon2Suite{})

func (*argon2Suite) TestMaybeRunArgon2OutOfProcessRequestHandlerArgon2Mode(c *C) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests might need to be renamed now

@@ -268,3 +269,17 @@ func MarkSuccessful() error {

return nil
}

func isOutOfProcessArgon2KDFMode(args []string) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should just have this in a small separate argon2_out_of_process.go ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Samuele review Needs a review from Samuele before it can land
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants