+PVE::JSONSchema::register_format('pve-tfa-config', \&verify_tfa_config);
+sub verify_tfa_config {
+ my ($value, $noerr) = @_;
+
+ return $value if parse_tfa_config($value);
+
+ return undef if $noerr;
+
+ die "unable to parse tfa option\n";
+}
+
+PVE::JSONSchema::register_standard_option('tfa', {
+ description => "Use Two-factor authentication.",
+ type => 'string', format => 'pve-tfa-config',
+ optional => 1,
+ maxLength => 128,
+});
+
+sub parse_tfa_config {
+ my ($data) = @_;
+
+ my $res = {};
+
+ foreach my $kvp (split(/,/, $data)) {
+
+ if ($kvp =~ m/^type=(yubico|oath)$/) {
+ $res->{type} = $1;
+ } elsif ($kvp =~ m/^id=(\S+)$/) {
+ $res->{id} = $1;
+ } elsif ($kvp =~ m/^key=(\S+)$/) {
+ $res->{key} = $1;
+ } elsif ($kvp =~ m/^url=(\S+)$/) {
+ $res->{url} = $1;
+ } elsif ($kvp =~ m/^digits=([6|7|8])$/) {
+ $res->{digits} = $1;
+ } elsif ($kvp =~ m/^step=([1-9]\d+)$/) {
+ $res->{step} = $1;
+ } else {
+ return undef;
+ }
+ }
+
+ return undef if !$res->{type};
+
+ return $res;
+}
+
+my $salt_starter = time();
+