PIV: More slot information and ability to generate pubkey only

This commit is contained in:
Dain Nilsson 2024-02-07 14:48:51 +01:00
parent fd288c947b
commit 0a6eedcc99
No known key found for this signature in database
GPG Key ID: F04367096FBA95E8
18 changed files with 427 additions and 349 deletions

View File

@ -75,6 +75,7 @@ class InvalidPinException(RpcException):
@unique @unique
class GENERATE_TYPE(str, Enum): class GENERATE_TYPE(str, Enum):
PUBLIC_KEY = "publicKey"
CSR = "csr" CSR = "csr"
CERTIFICATE = "certificate" CERTIFICATE = "certificate"
@ -304,7 +305,13 @@ def _get_cert_info(cert):
not_before = cert.not_valid_before not_before = cert.not_valid_before
not_after = cert.not_valid_after not_after = cert.not_valid_after
try:
key_type = KEY_TYPE.from_public_key(cert.public_key())
except ValueError:
key_type = None
return dict( return dict(
key_type=key_type,
subject=cert.subject.rfc4514_string(), subject=cert.subject.rfc4514_string(),
issuer=cert.issuer.rfc4514_string(), issuer=cert.issuer.rfc4514_string(),
serial=hex(cert.serial_number)[2:], serial=hex(cert.serial_number)[2:],
@ -348,7 +355,7 @@ class SlotsNode(RpcNode):
f"{int(slot):02x}": dict( f"{int(slot):02x}": dict(
slot=int(slot), slot=int(slot),
name=slot.name, name=slot.name,
has_key=metadata is not None if self._has_metadata else None, metadata=asdict(metadata) if metadata else None,
cert_info=_get_cert_info(cert), cert_info=_get_cert_info(cert),
) )
for slot, (metadata, cert) in self._slots.items() for slot, (metadata, cert) in self._slots.items()
@ -450,6 +457,9 @@ class SlotNode(RpcNode):
public_key = self.session.generate_key( public_key = self.session.generate_key(
self.slot, key_type, pin_policy, touch_policy self.slot, key_type, pin_policy, touch_policy
) )
public_key_pem = public_key.public_bytes(
encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo
).decode()
if pin_policy != PIN_POLICY.NEVER: if pin_policy != PIN_POLICY.NEVER:
# TODO: Check if verified? # TODO: Check if verified?
@ -459,7 +469,9 @@ class SlotNode(RpcNode):
if touch_policy in (TOUCH_POLICY.ALWAYS, TOUCH_POLICY.CACHED): if touch_policy in (TOUCH_POLICY.ALWAYS, TOUCH_POLICY.CACHED):
signal("touch") signal("touch")
if generate_type == GENERATE_TYPE.CSR: if generate_type == GENERATE_TYPE.PUBLIC_KEY:
result = public_key_pem
elif generate_type == GENERATE_TYPE.CSR:
csr = generate_csr(self.session, self.slot, public_key, subject) csr = generate_csr(self.session, self.slot, public_key, subject)
result = csr.public_bytes(encoding=Encoding.PEM).decode() result = csr.public_bytes(encoding=Encoding.PEM).decode()
elif generate_type == GENERATE_TYPE.CERTIFICATE: elif generate_type == GENERATE_TYPE.CERTIFICATE:
@ -479,13 +491,8 @@ class SlotNode(RpcNode):
self.session.put_certificate(self.slot, cert) self.session.put_certificate(self.slot, cert)
self.session.put_object(OBJECT_ID.CHUID, generate_chuid()) self.session.put_object(OBJECT_ID.CHUID, generate_chuid())
else: else:
raise ValueError("Unsupported GENERATE_TYPE") raise ValueError(f"Unsupported GENERATE_TYPE: {generate_type}")
self._refresh() self._refresh()
return dict( return dict(public_key=public_key_pem, result=result)
public_key=public_key.public_bytes(
encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo
).decode(),
result=result,
)

View File

@ -334,6 +334,12 @@ class _DesktopPivSlotsNotifier extends PivSlotsNotifier {
}); });
final (type, subject, validFrom, validTo) = parameters.when( final (type, subject, validFrom, validTo) = parameters.when(
publicKey: () => (
GenerateType.publicKey,
null,
null,
null,
),
certificate: (subject, validFrom, validTo) => ( certificate: (subject, validFrom, validTo) => (
GenerateType.certificate, GenerateType.certificate,
subject, subject,

View File

@ -79,6 +79,7 @@
"s_show_secret_key": null, "s_show_secret_key": null,
"s_hide_secret_key": null, "s_hide_secret_key": null,
"s_private_key": null, "s_private_key": null,
"s_public_key": null,
"s_invalid_length": "Ungültige Länge", "s_invalid_length": "Ungültige Länge",
"l_invalid_format_allowed_chars": null, "l_invalid_format_allowed_chars": null,
"@l_invalid_format_allowed_chars": { "@l_invalid_format_allowed_chars": {
@ -460,6 +461,7 @@
"s_csr": null, "s_csr": null,
"s_subject": null, "s_subject": null,
"l_export_csr_file": null, "l_export_csr_file": null,
"l_export_public_key_file": null,
"l_select_import_file": null, "l_select_import_file": null,
"l_export_certificate": null, "l_export_certificate": null,
"l_export_certificate_file": null, "l_export_certificate_file": null,

View File

@ -79,6 +79,7 @@
"s_show_secret_key": "Show secret key", "s_show_secret_key": "Show secret key",
"s_hide_secret_key": "Hide secret key", "s_hide_secret_key": "Hide secret key",
"s_private_key": "Private key", "s_private_key": "Private key",
"s_public_key": "Public key",
"s_invalid_length": "Invalid length", "s_invalid_length": "Invalid length",
"l_invalid_format_allowed_chars": "Invalid format, allowed characters: {characters}", "l_invalid_format_allowed_chars": "Invalid format, allowed characters: {characters}",
"@l_invalid_format_allowed_chars": { "@l_invalid_format_allowed_chars": {
@ -460,6 +461,7 @@
"s_csr": "CSR", "s_csr": "CSR",
"s_subject": "Subject", "s_subject": "Subject",
"l_export_csr_file": "Save CSR to file", "l_export_csr_file": "Save CSR to file",
"l_export_public_key_file": "Save public key to file",
"l_select_import_file": "Select file to import", "l_select_import_file": "Select file to import",
"l_export_certificate": "Export certificate", "l_export_certificate": "Export certificate",
"l_export_certificate_file": "Export certificate to file", "l_export_certificate_file": "Export certificate to file",

View File

@ -79,6 +79,7 @@
"s_show_secret_key": null, "s_show_secret_key": null,
"s_hide_secret_key": null, "s_hide_secret_key": null,
"s_private_key": "Clé privée", "s_private_key": "Clé privée",
"s_public_key": null,
"s_invalid_length": "Longueur invalide", "s_invalid_length": "Longueur invalide",
"l_invalid_format_allowed_chars": null, "l_invalid_format_allowed_chars": null,
"@l_invalid_format_allowed_chars": { "@l_invalid_format_allowed_chars": {
@ -460,6 +461,7 @@
"s_csr": "CSR", "s_csr": "CSR",
"s_subject": "Sujet", "s_subject": "Sujet",
"l_export_csr_file": "Sauvegarder le CSR vers un fichier", "l_export_csr_file": "Sauvegarder le CSR vers un fichier",
"l_export_public_key_file": null,
"l_select_import_file": "Sélectionnez un fichier à importer", "l_select_import_file": "Sélectionnez un fichier à importer",
"l_export_certificate": "Exporter le certificat", "l_export_certificate": "Exporter le certificat",
"l_export_certificate_file": "Exporter le certificat vers un fichier", "l_export_certificate_file": "Exporter le certificat vers un fichier",

View File

@ -79,6 +79,7 @@
"s_show_secret_key": null, "s_show_secret_key": null,
"s_hide_secret_key": null, "s_hide_secret_key": null,
"s_private_key": "秘密鍵", "s_private_key": "秘密鍵",
"s_public_key": null,
"s_invalid_length": "無効な長さです", "s_invalid_length": "無効な長さです",
"l_invalid_format_allowed_chars": null, "l_invalid_format_allowed_chars": null,
"@l_invalid_format_allowed_chars": { "@l_invalid_format_allowed_chars": {
@ -460,6 +461,7 @@
"s_csr": "CSR", "s_csr": "CSR",
"s_subject": "サブジェクト", "s_subject": "サブジェクト",
"l_export_csr_file": "CSRをファイルに保存", "l_export_csr_file": "CSRをファイルに保存",
"l_export_public_key_file": null,
"l_select_import_file": "インポートするファイルの選択", "l_select_import_file": "インポートするファイルの選択",
"l_export_certificate": "証明書をエクスポートする", "l_export_certificate": "証明書をエクスポートする",
"l_export_certificate_file": "証明書をファイルにエクスポートする", "l_export_certificate_file": "証明書をファイルにエクスポートする",

View File

@ -79,6 +79,7 @@
"s_show_secret_key": "Pokaż tajny klucz", "s_show_secret_key": "Pokaż tajny klucz",
"s_hide_secret_key": "Ukryj tajny klucz", "s_hide_secret_key": "Ukryj tajny klucz",
"s_private_key": "Klucz prywatny", "s_private_key": "Klucz prywatny",
"s_public_key": null,
"s_invalid_length": "Nieprawidłowa długość", "s_invalid_length": "Nieprawidłowa długość",
"l_invalid_format_allowed_chars": "Nieprawidłowy format, dozwolone znaki: {characters}", "l_invalid_format_allowed_chars": "Nieprawidłowy format, dozwolone znaki: {characters}",
"@l_invalid_format_allowed_chars": { "@l_invalid_format_allowed_chars": {
@ -460,6 +461,7 @@
"s_csr": "CSR", "s_csr": "CSR",
"s_subject": "Temat", "s_subject": "Temat",
"l_export_csr_file": "Zapisz CSR do pliku", "l_export_csr_file": "Zapisz CSR do pliku",
"l_export_public_key_file": null,
"l_select_import_file": "Wybierz plik do zaimportowania", "l_select_import_file": "Wybierz plik do zaimportowania",
"l_export_certificate": "Eksportuj certyfikat", "l_export_certificate": "Eksportuj certyfikat",
"l_export_certificate_file": "Eksportuj certyfikat do pliku", "l_export_certificate_file": "Eksportuj certyfikat do pliku",

View File

@ -56,11 +56,14 @@ const appListItem9c = Key('$_prefix.9c.applistitem');
const appListItem9d = Key('$_prefix.9d.applistitem'); const appListItem9d = Key('$_prefix.9d.applistitem');
const appListItem9e = Key('$_prefix.9e.applistitem'); const appListItem9e = Key('$_prefix.9e.applistitem');
// CertInfo body keys // SlotMetadata body keys
const slotMetadataKeyType = Key('$_prefix.slotMetadata.keyType');
const certInfoSubjectKey = Key('$_prefix.certInfo.subject'); // CertInfo body keys
const certInfoIssuerKey = Key('$_prefix.certInfo.issuer'); const certInfoKeyType = Key('$_prefix.certInfo.keyType');
const certInfoSerialKey = Key('$_prefix.certInfo.serial'); const certInfoSubject = Key('$_prefix.certInfo.subject');
const certInfoFingerprintKey = Key('$_prefix.certInfo.fingerprint'); const certInfoIssuer = Key('$_prefix.certInfo.issuer');
const certInfoValidFromKey = Key('$_prefix.certInfo.validFrom'); const certInfoSerial = Key('$_prefix.certInfo.serial');
const certInfoValidToKey = Key('$_prefix.certInfo.validTo'); const certInfoFingerprint = Key('$_prefix.certInfo.fingerprint');
const certInfoValidFrom = Key('$_prefix.certInfo.validFrom');
const certInfoValidTo = Key('$_prefix.certInfo.validTo');

View File

@ -28,12 +28,13 @@ const defaultKeyType = KeyType.eccp256;
const defaultGenerateType = GenerateType.certificate; const defaultGenerateType = GenerateType.certificate;
enum GenerateType { enum GenerateType {
// TODO: Add "publicKey"? Needed for X25519 publicKey,
certificate, certificate,
csr; csr;
String getDisplayName(AppLocalizations l10n) { String getDisplayName(AppLocalizations l10n) {
return switch (this) { return switch (this) {
GenerateType.publicKey => l10n.s_public_key,
GenerateType.certificate => l10n.s_certificate, GenerateType.certificate => l10n.s_certificate,
GenerateType.csr => l10n.s_csr, GenerateType.csr => l10n.s_csr,
}; };
@ -247,6 +248,7 @@ class PivState with _$PivState {
@freezed @freezed
class CertInfo with _$CertInfo { class CertInfo with _$CertInfo {
factory CertInfo({ factory CertInfo({
required KeyType? keyType,
required String subject, required String subject,
required String issuer, required String issuer,
required String serial, required String serial,
@ -263,7 +265,7 @@ class CertInfo with _$CertInfo {
class PivSlot with _$PivSlot { class PivSlot with _$PivSlot {
factory PivSlot({ factory PivSlot({
required SlotId slot, required SlotId slot,
bool? hasKey, SlotMetadata? metadata,
CertInfo? certInfo, CertInfo? certInfo,
}) = _PivSlot; }) = _PivSlot;
@ -286,11 +288,14 @@ class PivExamineResult with _$PivExamineResult {
@freezed @freezed
class PivGenerateParameters with _$PivGenerateParameters { class PivGenerateParameters with _$PivGenerateParameters {
factory PivGenerateParameters.publicKey() = _GeneratePublicKey;
factory PivGenerateParameters.certificate({ factory PivGenerateParameters.certificate({
required String subject, required String subject,
required DateTime validFrom, required DateTime validFrom,
required DateTime validTo, required DateTime validTo,
}) = _GenerateCertificate; }) = _GenerateCertificate;
factory PivGenerateParameters.csr({ factory PivGenerateParameters.csr({
required String subject, required String subject,
}) = _GenerateCsr; }) = _GenerateCsr;
@ -301,7 +306,7 @@ class PivGenerateResult with _$PivGenerateResult {
factory PivGenerateResult({ factory PivGenerateResult({
required GenerateType generateType, required GenerateType generateType,
required String publicKey, required String publicKey,
required String result, String? result,
}) = _PivGenerateResult; }) = _PivGenerateResult;
factory PivGenerateResult.fromJson(Map<String, dynamic> json) => factory PivGenerateResult.fromJson(Map<String, dynamic> json) =>

View File

@ -1431,6 +1431,7 @@ CertInfo _$CertInfoFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$CertInfo { mixin _$CertInfo {
KeyType? get keyType => throw _privateConstructorUsedError;
String get subject => throw _privateConstructorUsedError; String get subject => throw _privateConstructorUsedError;
String get issuer => throw _privateConstructorUsedError; String get issuer => throw _privateConstructorUsedError;
String get serial => throw _privateConstructorUsedError; String get serial => throw _privateConstructorUsedError;
@ -1450,7 +1451,8 @@ abstract class $CertInfoCopyWith<$Res> {
_$CertInfoCopyWithImpl<$Res, CertInfo>; _$CertInfoCopyWithImpl<$Res, CertInfo>;
@useResult @useResult
$Res call( $Res call(
{String subject, {KeyType? keyType,
String subject,
String issuer, String issuer,
String serial, String serial,
String notValidBefore, String notValidBefore,
@ -1471,6 +1473,7 @@ class _$CertInfoCopyWithImpl<$Res, $Val extends CertInfo>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? keyType = freezed,
Object? subject = null, Object? subject = null,
Object? issuer = null, Object? issuer = null,
Object? serial = null, Object? serial = null,
@ -1479,6 +1482,10 @@ class _$CertInfoCopyWithImpl<$Res, $Val extends CertInfo>
Object? fingerprint = null, Object? fingerprint = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
keyType: freezed == keyType
? _value.keyType
: keyType // ignore: cast_nullable_to_non_nullable
as KeyType?,
subject: null == subject subject: null == subject
? _value.subject ? _value.subject
: subject // ignore: cast_nullable_to_non_nullable : subject // ignore: cast_nullable_to_non_nullable
@ -1516,7 +1523,8 @@ abstract class _$$CertInfoImplCopyWith<$Res>
@override @override
@useResult @useResult
$Res call( $Res call(
{String subject, {KeyType? keyType,
String subject,
String issuer, String issuer,
String serial, String serial,
String notValidBefore, String notValidBefore,
@ -1535,6 +1543,7 @@ class __$$CertInfoImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? keyType = freezed,
Object? subject = null, Object? subject = null,
Object? issuer = null, Object? issuer = null,
Object? serial = null, Object? serial = null,
@ -1543,6 +1552,10 @@ class __$$CertInfoImplCopyWithImpl<$Res>
Object? fingerprint = null, Object? fingerprint = null,
}) { }) {
return _then(_$CertInfoImpl( return _then(_$CertInfoImpl(
keyType: freezed == keyType
? _value.keyType
: keyType // ignore: cast_nullable_to_non_nullable
as KeyType?,
subject: null == subject subject: null == subject
? _value.subject ? _value.subject
: subject // ignore: cast_nullable_to_non_nullable : subject // ignore: cast_nullable_to_non_nullable
@ -1575,7 +1588,8 @@ class __$$CertInfoImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$CertInfoImpl implements _CertInfo { class _$CertInfoImpl implements _CertInfo {
_$CertInfoImpl( _$CertInfoImpl(
{required this.subject, {required this.keyType,
required this.subject,
required this.issuer, required this.issuer,
required this.serial, required this.serial,
required this.notValidBefore, required this.notValidBefore,
@ -1585,6 +1599,8 @@ class _$CertInfoImpl implements _CertInfo {
factory _$CertInfoImpl.fromJson(Map<String, dynamic> json) => factory _$CertInfoImpl.fromJson(Map<String, dynamic> json) =>
_$$CertInfoImplFromJson(json); _$$CertInfoImplFromJson(json);
@override
final KeyType? keyType;
@override @override
final String subject; final String subject;
@override @override
@ -1600,7 +1616,7 @@ class _$CertInfoImpl implements _CertInfo {
@override @override
String toString() { String toString() {
return 'CertInfo(subject: $subject, issuer: $issuer, serial: $serial, notValidBefore: $notValidBefore, notValidAfter: $notValidAfter, fingerprint: $fingerprint)'; return 'CertInfo(keyType: $keyType, subject: $subject, issuer: $issuer, serial: $serial, notValidBefore: $notValidBefore, notValidAfter: $notValidAfter, fingerprint: $fingerprint)';
} }
@override @override
@ -1608,6 +1624,7 @@ class _$CertInfoImpl implements _CertInfo {
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$CertInfoImpl && other is _$CertInfoImpl &&
(identical(other.keyType, keyType) || other.keyType == keyType) &&
(identical(other.subject, subject) || other.subject == subject) && (identical(other.subject, subject) || other.subject == subject) &&
(identical(other.issuer, issuer) || other.issuer == issuer) && (identical(other.issuer, issuer) || other.issuer == issuer) &&
(identical(other.serial, serial) || other.serial == serial) && (identical(other.serial, serial) || other.serial == serial) &&
@ -1621,7 +1638,7 @@ class _$CertInfoImpl implements _CertInfo {
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash(runtimeType, subject, issuer, serial, int get hashCode => Object.hash(runtimeType, keyType, subject, issuer, serial,
notValidBefore, notValidAfter, fingerprint); notValidBefore, notValidAfter, fingerprint);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@ -1640,7 +1657,8 @@ class _$CertInfoImpl implements _CertInfo {
abstract class _CertInfo implements CertInfo { abstract class _CertInfo implements CertInfo {
factory _CertInfo( factory _CertInfo(
{required final String subject, {required final KeyType? keyType,
required final String subject,
required final String issuer, required final String issuer,
required final String serial, required final String serial,
required final String notValidBefore, required final String notValidBefore,
@ -1650,6 +1668,8 @@ abstract class _CertInfo implements CertInfo {
factory _CertInfo.fromJson(Map<String, dynamic> json) = factory _CertInfo.fromJson(Map<String, dynamic> json) =
_$CertInfoImpl.fromJson; _$CertInfoImpl.fromJson;
@override
KeyType? get keyType;
@override @override
String get subject; String get subject;
@override @override
@ -1675,7 +1695,7 @@ PivSlot _$PivSlotFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$PivSlot { mixin _$PivSlot {
SlotId get slot => throw _privateConstructorUsedError; SlotId get slot => throw _privateConstructorUsedError;
bool? get hasKey => throw _privateConstructorUsedError; SlotMetadata? get metadata => throw _privateConstructorUsedError;
CertInfo? get certInfo => throw _privateConstructorUsedError; CertInfo? get certInfo => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@ -1688,8 +1708,9 @@ abstract class $PivSlotCopyWith<$Res> {
factory $PivSlotCopyWith(PivSlot value, $Res Function(PivSlot) then) = factory $PivSlotCopyWith(PivSlot value, $Res Function(PivSlot) then) =
_$PivSlotCopyWithImpl<$Res, PivSlot>; _$PivSlotCopyWithImpl<$Res, PivSlot>;
@useResult @useResult
$Res call({SlotId slot, bool? hasKey, CertInfo? certInfo}); $Res call({SlotId slot, SlotMetadata? metadata, CertInfo? certInfo});
$SlotMetadataCopyWith<$Res>? get metadata;
$CertInfoCopyWith<$Res>? get certInfo; $CertInfoCopyWith<$Res>? get certInfo;
} }
@ -1707,7 +1728,7 @@ class _$PivSlotCopyWithImpl<$Res, $Val extends PivSlot>
@override @override
$Res call({ $Res call({
Object? slot = null, Object? slot = null,
Object? hasKey = freezed, Object? metadata = freezed,
Object? certInfo = freezed, Object? certInfo = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
@ -1715,10 +1736,10 @@ class _$PivSlotCopyWithImpl<$Res, $Val extends PivSlot>
? _value.slot ? _value.slot
: slot // ignore: cast_nullable_to_non_nullable : slot // ignore: cast_nullable_to_non_nullable
as SlotId, as SlotId,
hasKey: freezed == hasKey metadata: freezed == metadata
? _value.hasKey ? _value.metadata
: hasKey // ignore: cast_nullable_to_non_nullable : metadata // ignore: cast_nullable_to_non_nullable
as bool?, as SlotMetadata?,
certInfo: freezed == certInfo certInfo: freezed == certInfo
? _value.certInfo ? _value.certInfo
: certInfo // ignore: cast_nullable_to_non_nullable : certInfo // ignore: cast_nullable_to_non_nullable
@ -1726,6 +1747,18 @@ class _$PivSlotCopyWithImpl<$Res, $Val extends PivSlot>
) as $Val); ) as $Val);
} }
@override
@pragma('vm:prefer-inline')
$SlotMetadataCopyWith<$Res>? get metadata {
if (_value.metadata == null) {
return null;
}
return $SlotMetadataCopyWith<$Res>(_value.metadata!, (value) {
return _then(_value.copyWith(metadata: value) as $Val);
});
}
@override @override
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
$CertInfoCopyWith<$Res>? get certInfo { $CertInfoCopyWith<$Res>? get certInfo {
@ -1746,8 +1779,10 @@ abstract class _$$PivSlotImplCopyWith<$Res> implements $PivSlotCopyWith<$Res> {
__$$PivSlotImplCopyWithImpl<$Res>; __$$PivSlotImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({SlotId slot, bool? hasKey, CertInfo? certInfo}); $Res call({SlotId slot, SlotMetadata? metadata, CertInfo? certInfo});
@override
$SlotMetadataCopyWith<$Res>? get metadata;
@override @override
$CertInfoCopyWith<$Res>? get certInfo; $CertInfoCopyWith<$Res>? get certInfo;
} }
@ -1764,7 +1799,7 @@ class __$$PivSlotImplCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? slot = null, Object? slot = null,
Object? hasKey = freezed, Object? metadata = freezed,
Object? certInfo = freezed, Object? certInfo = freezed,
}) { }) {
return _then(_$PivSlotImpl( return _then(_$PivSlotImpl(
@ -1772,10 +1807,10 @@ class __$$PivSlotImplCopyWithImpl<$Res>
? _value.slot ? _value.slot
: slot // ignore: cast_nullable_to_non_nullable : slot // ignore: cast_nullable_to_non_nullable
as SlotId, as SlotId,
hasKey: freezed == hasKey metadata: freezed == metadata
? _value.hasKey ? _value.metadata
: hasKey // ignore: cast_nullable_to_non_nullable : metadata // ignore: cast_nullable_to_non_nullable
as bool?, as SlotMetadata?,
certInfo: freezed == certInfo certInfo: freezed == certInfo
? _value.certInfo ? _value.certInfo
: certInfo // ignore: cast_nullable_to_non_nullable : certInfo // ignore: cast_nullable_to_non_nullable
@ -1787,7 +1822,7 @@ class __$$PivSlotImplCopyWithImpl<$Res>
/// @nodoc /// @nodoc
@JsonSerializable() @JsonSerializable()
class _$PivSlotImpl implements _PivSlot { class _$PivSlotImpl implements _PivSlot {
_$PivSlotImpl({required this.slot, this.hasKey, this.certInfo}); _$PivSlotImpl({required this.slot, this.metadata, this.certInfo});
factory _$PivSlotImpl.fromJson(Map<String, dynamic> json) => factory _$PivSlotImpl.fromJson(Map<String, dynamic> json) =>
_$$PivSlotImplFromJson(json); _$$PivSlotImplFromJson(json);
@ -1795,13 +1830,13 @@ class _$PivSlotImpl implements _PivSlot {
@override @override
final SlotId slot; final SlotId slot;
@override @override
final bool? hasKey; final SlotMetadata? metadata;
@override @override
final CertInfo? certInfo; final CertInfo? certInfo;
@override @override
String toString() { String toString() {
return 'PivSlot(slot: $slot, hasKey: $hasKey, certInfo: $certInfo)'; return 'PivSlot(slot: $slot, metadata: $metadata, certInfo: $certInfo)';
} }
@override @override
@ -1810,14 +1845,15 @@ class _$PivSlotImpl implements _PivSlot {
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$PivSlotImpl && other is _$PivSlotImpl &&
(identical(other.slot, slot) || other.slot == slot) && (identical(other.slot, slot) || other.slot == slot) &&
(identical(other.hasKey, hasKey) || other.hasKey == hasKey) && (identical(other.metadata, metadata) ||
other.metadata == metadata) &&
(identical(other.certInfo, certInfo) || (identical(other.certInfo, certInfo) ||
other.certInfo == certInfo)); other.certInfo == certInfo));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash(runtimeType, slot, hasKey, certInfo); int get hashCode => Object.hash(runtimeType, slot, metadata, certInfo);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@ -1836,7 +1872,7 @@ class _$PivSlotImpl implements _PivSlot {
abstract class _PivSlot implements PivSlot { abstract class _PivSlot implements PivSlot {
factory _PivSlot( factory _PivSlot(
{required final SlotId slot, {required final SlotId slot,
final bool? hasKey, final SlotMetadata? metadata,
final CertInfo? certInfo}) = _$PivSlotImpl; final CertInfo? certInfo}) = _$PivSlotImpl;
factory _PivSlot.fromJson(Map<String, dynamic> json) = _$PivSlotImpl.fromJson; factory _PivSlot.fromJson(Map<String, dynamic> json) = _$PivSlotImpl.fromJson;
@ -1844,7 +1880,7 @@ abstract class _PivSlot implements PivSlot {
@override @override
SlotId get slot; SlotId get slot;
@override @override
bool? get hasKey; SlotMetadata? get metadata;
@override @override
CertInfo? get certInfo; CertInfo? get certInfo;
@override @override
@ -2253,9 +2289,9 @@ abstract class _InvalidPassword implements PivExamineResult {
/// @nodoc /// @nodoc
mixin _$PivGenerateParameters { mixin _$PivGenerateParameters {
String get subject => throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult when<TResult extends Object?>({ TResult when<TResult extends Object?>({
required TResult Function() publicKey,
required TResult Function( required TResult Function(
String subject, DateTime validFrom, DateTime validTo) String subject, DateTime validFrom, DateTime validTo)
certificate, certificate,
@ -2264,6 +2300,7 @@ mixin _$PivGenerateParameters {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? publicKey,
TResult? Function(String subject, DateTime validFrom, DateTime validTo)? TResult? Function(String subject, DateTime validFrom, DateTime validTo)?
certificate, certificate,
TResult? Function(String subject)? csr, TResult? Function(String subject)? csr,
@ -2271,6 +2308,7 @@ mixin _$PivGenerateParameters {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({ TResult maybeWhen<TResult extends Object?>({
TResult Function()? publicKey,
TResult Function(String subject, DateTime validFrom, DateTime validTo)? TResult Function(String subject, DateTime validFrom, DateTime validTo)?
certificate, certificate,
TResult Function(String subject)? csr, TResult Function(String subject)? csr,
@ -2279,27 +2317,26 @@ mixin _$PivGenerateParameters {
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult map<TResult extends Object?>({ TResult map<TResult extends Object?>({
required TResult Function(_GeneratePublicKey value) publicKey,
required TResult Function(_GenerateCertificate value) certificate, required TResult Function(_GenerateCertificate value) certificate,
required TResult Function(_GenerateCsr value) csr, required TResult Function(_GenerateCsr value) csr,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_GeneratePublicKey value)? publicKey,
TResult? Function(_GenerateCertificate value)? certificate, TResult? Function(_GenerateCertificate value)? certificate,
TResult? Function(_GenerateCsr value)? csr, TResult? Function(_GenerateCsr value)? csr,
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@optionalTypeArgs @optionalTypeArgs
TResult maybeMap<TResult extends Object?>({ TResult maybeMap<TResult extends Object?>({
TResult Function(_GeneratePublicKey value)? publicKey,
TResult Function(_GenerateCertificate value)? certificate, TResult Function(_GenerateCertificate value)? certificate,
TResult Function(_GenerateCsr value)? csr, TResult Function(_GenerateCsr value)? csr,
required TResult orElse(), required TResult orElse(),
}) => }) =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$PivGenerateParametersCopyWith<PivGenerateParameters> get copyWith =>
throw _privateConstructorUsedError;
} }
/// @nodoc /// @nodoc
@ -2307,8 +2344,6 @@ abstract class $PivGenerateParametersCopyWith<$Res> {
factory $PivGenerateParametersCopyWith(PivGenerateParameters value, factory $PivGenerateParametersCopyWith(PivGenerateParameters value,
$Res Function(PivGenerateParameters) then) = $Res Function(PivGenerateParameters) then) =
_$PivGenerateParametersCopyWithImpl<$Res, PivGenerateParameters>; _$PivGenerateParametersCopyWithImpl<$Res, PivGenerateParameters>;
@useResult
$Res call({String subject});
} }
/// @nodoc /// @nodoc
@ -2321,28 +2356,125 @@ class _$PivGenerateParametersCopyWithImpl<$Res,
final $Val _value; final $Val _value;
// ignore: unused_field // ignore: unused_field
final $Res Function($Val) _then; final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? subject = null,
}) {
return _then(_value.copyWith(
subject: null == subject
? _value.subject
: subject // ignore: cast_nullable_to_non_nullable
as String,
) as $Val);
}
} }
/// @nodoc /// @nodoc
abstract class _$$GenerateCertificateImplCopyWith<$Res> abstract class _$$GeneratePublicKeyImplCopyWith<$Res> {
implements $PivGenerateParametersCopyWith<$Res> { factory _$$GeneratePublicKeyImplCopyWith(_$GeneratePublicKeyImpl value,
$Res Function(_$GeneratePublicKeyImpl) then) =
__$$GeneratePublicKeyImplCopyWithImpl<$Res>;
}
/// @nodoc
class __$$GeneratePublicKeyImplCopyWithImpl<$Res>
extends _$PivGenerateParametersCopyWithImpl<$Res, _$GeneratePublicKeyImpl>
implements _$$GeneratePublicKeyImplCopyWith<$Res> {
__$$GeneratePublicKeyImplCopyWithImpl(_$GeneratePublicKeyImpl _value,
$Res Function(_$GeneratePublicKeyImpl) _then)
: super(_value, _then);
}
/// @nodoc
class _$GeneratePublicKeyImpl implements _GeneratePublicKey {
_$GeneratePublicKeyImpl();
@override
String toString() {
return 'PivGenerateParameters.publicKey()';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType && other is _$GeneratePublicKeyImpl);
}
@override
int get hashCode => runtimeType.hashCode;
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() publicKey,
required TResult Function(
String subject, DateTime validFrom, DateTime validTo)
certificate,
required TResult Function(String subject) csr,
}) {
return publicKey();
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? publicKey,
TResult? Function(String subject, DateTime validFrom, DateTime validTo)?
certificate,
TResult? Function(String subject)? csr,
}) {
return publicKey?.call();
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function()? publicKey,
TResult Function(String subject, DateTime validFrom, DateTime validTo)?
certificate,
TResult Function(String subject)? csr,
required TResult orElse(),
}) {
if (publicKey != null) {
return publicKey();
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(_GeneratePublicKey value) publicKey,
required TResult Function(_GenerateCertificate value) certificate,
required TResult Function(_GenerateCsr value) csr,
}) {
return publicKey(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_GeneratePublicKey value)? publicKey,
TResult? Function(_GenerateCertificate value)? certificate,
TResult? Function(_GenerateCsr value)? csr,
}) {
return publicKey?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(_GeneratePublicKey value)? publicKey,
TResult Function(_GenerateCertificate value)? certificate,
TResult Function(_GenerateCsr value)? csr,
required TResult orElse(),
}) {
if (publicKey != null) {
return publicKey(this);
}
return orElse();
}
}
abstract class _GeneratePublicKey implements PivGenerateParameters {
factory _GeneratePublicKey() = _$GeneratePublicKeyImpl;
}
/// @nodoc
abstract class _$$GenerateCertificateImplCopyWith<$Res> {
factory _$$GenerateCertificateImplCopyWith(_$GenerateCertificateImpl value, factory _$$GenerateCertificateImplCopyWith(_$GenerateCertificateImpl value,
$Res Function(_$GenerateCertificateImpl) then) = $Res Function(_$GenerateCertificateImpl) then) =
__$$GenerateCertificateImplCopyWithImpl<$Res>; __$$GenerateCertificateImplCopyWithImpl<$Res>;
@override
@useResult @useResult
$Res call({String subject, DateTime validFrom, DateTime validTo}); $Res call({String subject, DateTime validFrom, DateTime validTo});
} }
@ -2421,6 +2553,7 @@ class _$GenerateCertificateImpl implements _GenerateCertificate {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult when<TResult extends Object?>({ TResult when<TResult extends Object?>({
required TResult Function() publicKey,
required TResult Function( required TResult Function(
String subject, DateTime validFrom, DateTime validTo) String subject, DateTime validFrom, DateTime validTo)
certificate, certificate,
@ -2432,6 +2565,7 @@ class _$GenerateCertificateImpl implements _GenerateCertificate {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? publicKey,
TResult? Function(String subject, DateTime validFrom, DateTime validTo)? TResult? Function(String subject, DateTime validFrom, DateTime validTo)?
certificate, certificate,
TResult? Function(String subject)? csr, TResult? Function(String subject)? csr,
@ -2442,6 +2576,7 @@ class _$GenerateCertificateImpl implements _GenerateCertificate {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({ TResult maybeWhen<TResult extends Object?>({
TResult Function()? publicKey,
TResult Function(String subject, DateTime validFrom, DateTime validTo)? TResult Function(String subject, DateTime validFrom, DateTime validTo)?
certificate, certificate,
TResult Function(String subject)? csr, TResult Function(String subject)? csr,
@ -2456,6 +2591,7 @@ class _$GenerateCertificateImpl implements _GenerateCertificate {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult map<TResult extends Object?>({ TResult map<TResult extends Object?>({
required TResult Function(_GeneratePublicKey value) publicKey,
required TResult Function(_GenerateCertificate value) certificate, required TResult Function(_GenerateCertificate value) certificate,
required TResult Function(_GenerateCsr value) csr, required TResult Function(_GenerateCsr value) csr,
}) { }) {
@ -2465,6 +2601,7 @@ class _$GenerateCertificateImpl implements _GenerateCertificate {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_GeneratePublicKey value)? publicKey,
TResult? Function(_GenerateCertificate value)? certificate, TResult? Function(_GenerateCertificate value)? certificate,
TResult? Function(_GenerateCsr value)? csr, TResult? Function(_GenerateCsr value)? csr,
}) { }) {
@ -2474,6 +2611,7 @@ class _$GenerateCertificateImpl implements _GenerateCertificate {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult maybeMap<TResult extends Object?>({ TResult maybeMap<TResult extends Object?>({
TResult Function(_GeneratePublicKey value)? publicKey,
TResult Function(_GenerateCertificate value)? certificate, TResult Function(_GenerateCertificate value)? certificate,
TResult Function(_GenerateCsr value)? csr, TResult Function(_GenerateCsr value)? csr,
required TResult orElse(), required TResult orElse(),
@ -2491,23 +2629,19 @@ abstract class _GenerateCertificate implements PivGenerateParameters {
required final DateTime validFrom, required final DateTime validFrom,
required final DateTime validTo}) = _$GenerateCertificateImpl; required final DateTime validTo}) = _$GenerateCertificateImpl;
@override
String get subject; String get subject;
DateTime get validFrom; DateTime get validFrom;
DateTime get validTo; DateTime get validTo;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$GenerateCertificateImplCopyWith<_$GenerateCertificateImpl> get copyWith => _$$GenerateCertificateImplCopyWith<_$GenerateCertificateImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
/// @nodoc /// @nodoc
abstract class _$$GenerateCsrImplCopyWith<$Res> abstract class _$$GenerateCsrImplCopyWith<$Res> {
implements $PivGenerateParametersCopyWith<$Res> {
factory _$$GenerateCsrImplCopyWith( factory _$$GenerateCsrImplCopyWith(
_$GenerateCsrImpl value, $Res Function(_$GenerateCsrImpl) then) = _$GenerateCsrImpl value, $Res Function(_$GenerateCsrImpl) then) =
__$$GenerateCsrImplCopyWithImpl<$Res>; __$$GenerateCsrImplCopyWithImpl<$Res>;
@override
@useResult @useResult
$Res call({String subject}); $Res call({String subject});
} }
@ -2567,6 +2701,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult when<TResult extends Object?>({ TResult when<TResult extends Object?>({
required TResult Function() publicKey,
required TResult Function( required TResult Function(
String subject, DateTime validFrom, DateTime validTo) String subject, DateTime validFrom, DateTime validTo)
certificate, certificate,
@ -2578,6 +2713,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({ TResult? whenOrNull<TResult extends Object?>({
TResult? Function()? publicKey,
TResult? Function(String subject, DateTime validFrom, DateTime validTo)? TResult? Function(String subject, DateTime validFrom, DateTime validTo)?
certificate, certificate,
TResult? Function(String subject)? csr, TResult? Function(String subject)? csr,
@ -2588,6 +2724,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({ TResult maybeWhen<TResult extends Object?>({
TResult Function()? publicKey,
TResult Function(String subject, DateTime validFrom, DateTime validTo)? TResult Function(String subject, DateTime validFrom, DateTime validTo)?
certificate, certificate,
TResult Function(String subject)? csr, TResult Function(String subject)? csr,
@ -2602,6 +2739,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult map<TResult extends Object?>({ TResult map<TResult extends Object?>({
required TResult Function(_GeneratePublicKey value) publicKey,
required TResult Function(_GenerateCertificate value) certificate, required TResult Function(_GenerateCertificate value) certificate,
required TResult Function(_GenerateCsr value) csr, required TResult Function(_GenerateCsr value) csr,
}) { }) {
@ -2611,6 +2749,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({ TResult? mapOrNull<TResult extends Object?>({
TResult? Function(_GeneratePublicKey value)? publicKey,
TResult? Function(_GenerateCertificate value)? certificate, TResult? Function(_GenerateCertificate value)? certificate,
TResult? Function(_GenerateCsr value)? csr, TResult? Function(_GenerateCsr value)? csr,
}) { }) {
@ -2620,6 +2759,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
@override @override
@optionalTypeArgs @optionalTypeArgs
TResult maybeMap<TResult extends Object?>({ TResult maybeMap<TResult extends Object?>({
TResult Function(_GeneratePublicKey value)? publicKey,
TResult Function(_GenerateCertificate value)? certificate, TResult Function(_GenerateCertificate value)? certificate,
TResult Function(_GenerateCsr value)? csr, TResult Function(_GenerateCsr value)? csr,
required TResult orElse(), required TResult orElse(),
@ -2634,9 +2774,7 @@ class _$GenerateCsrImpl implements _GenerateCsr {
abstract class _GenerateCsr implements PivGenerateParameters { abstract class _GenerateCsr implements PivGenerateParameters {
factory _GenerateCsr({required final String subject}) = _$GenerateCsrImpl; factory _GenerateCsr({required final String subject}) = _$GenerateCsrImpl;
@override
String get subject; String get subject;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$GenerateCsrImplCopyWith<_$GenerateCsrImpl> get copyWith => _$$GenerateCsrImplCopyWith<_$GenerateCsrImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
@ -2650,7 +2788,7 @@ PivGenerateResult _$PivGenerateResultFromJson(Map<String, dynamic> json) {
mixin _$PivGenerateResult { mixin _$PivGenerateResult {
GenerateType get generateType => throw _privateConstructorUsedError; GenerateType get generateType => throw _privateConstructorUsedError;
String get publicKey => throw _privateConstructorUsedError; String get publicKey => throw _privateConstructorUsedError;
String get result => throw _privateConstructorUsedError; String? get result => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
@ -2664,7 +2802,7 @@ abstract class $PivGenerateResultCopyWith<$Res> {
PivGenerateResult value, $Res Function(PivGenerateResult) then) = PivGenerateResult value, $Res Function(PivGenerateResult) then) =
_$PivGenerateResultCopyWithImpl<$Res, PivGenerateResult>; _$PivGenerateResultCopyWithImpl<$Res, PivGenerateResult>;
@useResult @useResult
$Res call({GenerateType generateType, String publicKey, String result}); $Res call({GenerateType generateType, String publicKey, String? result});
} }
/// @nodoc /// @nodoc
@ -2682,7 +2820,7 @@ class _$PivGenerateResultCopyWithImpl<$Res, $Val extends PivGenerateResult>
$Res call({ $Res call({
Object? generateType = null, Object? generateType = null,
Object? publicKey = null, Object? publicKey = null,
Object? result = null, Object? result = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
generateType: null == generateType generateType: null == generateType
@ -2693,10 +2831,10 @@ class _$PivGenerateResultCopyWithImpl<$Res, $Val extends PivGenerateResult>
? _value.publicKey ? _value.publicKey
: publicKey // ignore: cast_nullable_to_non_nullable : publicKey // ignore: cast_nullable_to_non_nullable
as String, as String,
result: null == result result: freezed == result
? _value.result ? _value.result
: result // ignore: cast_nullable_to_non_nullable : result // ignore: cast_nullable_to_non_nullable
as String, as String?,
) as $Val); ) as $Val);
} }
} }
@ -2709,7 +2847,7 @@ abstract class _$$PivGenerateResultImplCopyWith<$Res>
__$$PivGenerateResultImplCopyWithImpl<$Res>; __$$PivGenerateResultImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({GenerateType generateType, String publicKey, String result}); $Res call({GenerateType generateType, String publicKey, String? result});
} }
/// @nodoc /// @nodoc
@ -2725,7 +2863,7 @@ class __$$PivGenerateResultImplCopyWithImpl<$Res>
$Res call({ $Res call({
Object? generateType = null, Object? generateType = null,
Object? publicKey = null, Object? publicKey = null,
Object? result = null, Object? result = freezed,
}) { }) {
return _then(_$PivGenerateResultImpl( return _then(_$PivGenerateResultImpl(
generateType: null == generateType generateType: null == generateType
@ -2736,10 +2874,10 @@ class __$$PivGenerateResultImplCopyWithImpl<$Res>
? _value.publicKey ? _value.publicKey
: publicKey // ignore: cast_nullable_to_non_nullable : publicKey // ignore: cast_nullable_to_non_nullable
as String, as String,
result: null == result result: freezed == result
? _value.result ? _value.result
: result // ignore: cast_nullable_to_non_nullable : result // ignore: cast_nullable_to_non_nullable
as String, as String?,
)); ));
} }
} }
@ -2748,9 +2886,7 @@ class __$$PivGenerateResultImplCopyWithImpl<$Res>
@JsonSerializable() @JsonSerializable()
class _$PivGenerateResultImpl implements _PivGenerateResult { class _$PivGenerateResultImpl implements _PivGenerateResult {
_$PivGenerateResultImpl( _$PivGenerateResultImpl(
{required this.generateType, {required this.generateType, required this.publicKey, this.result});
required this.publicKey,
required this.result});
factory _$PivGenerateResultImpl.fromJson(Map<String, dynamic> json) => factory _$PivGenerateResultImpl.fromJson(Map<String, dynamic> json) =>
_$$PivGenerateResultImplFromJson(json); _$$PivGenerateResultImplFromJson(json);
@ -2760,7 +2896,7 @@ class _$PivGenerateResultImpl implements _PivGenerateResult {
@override @override
final String publicKey; final String publicKey;
@override @override
final String result; final String? result;
@override @override
String toString() { String toString() {
@ -2802,7 +2938,7 @@ abstract class _PivGenerateResult implements PivGenerateResult {
factory _PivGenerateResult( factory _PivGenerateResult(
{required final GenerateType generateType, {required final GenerateType generateType,
required final String publicKey, required final String publicKey,
required final String result}) = _$PivGenerateResultImpl; final String? result}) = _$PivGenerateResultImpl;
factory _PivGenerateResult.fromJson(Map<String, dynamic> json) = factory _PivGenerateResult.fromJson(Map<String, dynamic> json) =
_$PivGenerateResultImpl.fromJson; _$PivGenerateResultImpl.fromJson;
@ -2812,7 +2948,7 @@ abstract class _PivGenerateResult implements PivGenerateResult {
@override @override
String get publicKey; String get publicKey;
@override @override
String get result; String? get result;
@override @override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$PivGenerateResultImplCopyWith<_$PivGenerateResultImpl> get copyWith => _$$PivGenerateResultImplCopyWith<_$PivGenerateResultImpl> get copyWith =>

View File

@ -133,6 +133,7 @@ Map<String, dynamic> _$$PivStateImplToJson(_$PivStateImpl instance) =>
_$CertInfoImpl _$$CertInfoImplFromJson(Map<String, dynamic> json) => _$CertInfoImpl _$$CertInfoImplFromJson(Map<String, dynamic> json) =>
_$CertInfoImpl( _$CertInfoImpl(
keyType: $enumDecodeNullable(_$KeyTypeEnumMap, json['key_type']),
subject: json['subject'] as String, subject: json['subject'] as String,
issuer: json['issuer'] as String, issuer: json['issuer'] as String,
serial: json['serial'] as String, serial: json['serial'] as String,
@ -143,6 +144,7 @@ _$CertInfoImpl _$$CertInfoImplFromJson(Map<String, dynamic> json) =>
Map<String, dynamic> _$$CertInfoImplToJson(_$CertInfoImpl instance) => Map<String, dynamic> _$$CertInfoImplToJson(_$CertInfoImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'key_type': _$KeyTypeEnumMap[instance.keyType],
'subject': instance.subject, 'subject': instance.subject,
'issuer': instance.issuer, 'issuer': instance.issuer,
'serial': instance.serial, 'serial': instance.serial,
@ -154,7 +156,9 @@ Map<String, dynamic> _$$CertInfoImplToJson(_$CertInfoImpl instance) =>
_$PivSlotImpl _$$PivSlotImplFromJson(Map<String, dynamic> json) => _$PivSlotImpl _$$PivSlotImplFromJson(Map<String, dynamic> json) =>
_$PivSlotImpl( _$PivSlotImpl(
slot: SlotId.fromJson(json['slot'] as int), slot: SlotId.fromJson(json['slot'] as int),
hasKey: json['has_key'] as bool?, metadata: json['metadata'] == null
? null
: SlotMetadata.fromJson(json['metadata'] as Map<String, dynamic>),
certInfo: json['cert_info'] == null certInfo: json['cert_info'] == null
? null ? null
: CertInfo.fromJson(json['cert_info'] as Map<String, dynamic>), : CertInfo.fromJson(json['cert_info'] as Map<String, dynamic>),
@ -163,7 +167,7 @@ _$PivSlotImpl _$$PivSlotImplFromJson(Map<String, dynamic> json) =>
Map<String, dynamic> _$$PivSlotImplToJson(_$PivSlotImpl instance) => Map<String, dynamic> _$$PivSlotImplToJson(_$PivSlotImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'slot': _$SlotIdEnumMap[instance.slot]!, 'slot': _$SlotIdEnumMap[instance.slot]!,
'has_key': instance.hasKey, 'metadata': instance.metadata,
'cert_info': instance.certInfo, 'cert_info': instance.certInfo,
}; };
@ -209,7 +213,7 @@ _$PivGenerateResultImpl _$$PivGenerateResultImplFromJson(
_$PivGenerateResultImpl( _$PivGenerateResultImpl(
generateType: $enumDecode(_$GenerateTypeEnumMap, json['generate_type']), generateType: $enumDecode(_$GenerateTypeEnumMap, json['generate_type']),
publicKey: json['public_key'] as String, publicKey: json['public_key'] as String,
result: json['result'] as String, result: json['result'] as String?,
); );
Map<String, dynamic> _$$PivGenerateResultImplToJson( Map<String, dynamic> _$$PivGenerateResultImplToJson(
@ -221,6 +225,7 @@ Map<String, dynamic> _$$PivGenerateResultImplToJson(
}; };
const _$GenerateTypeEnumMap = { const _$GenerateTypeEnumMap = {
GenerateType.publicKey: 'publicKey',
GenerateType.certificate: 'certificate', GenerateType.certificate: 'certificate',
GenerateType.csr: 'csr', GenerateType.csr: 'csr',
}; };

View File

@ -123,21 +123,33 @@ class PivActions extends ConsumerWidget {
), ),
); );
switch (result?.generateType) { if (result != null) {
case GenerateType.csr: final (fileExt, title, data) = switch (result.generateType) {
GenerateType.publicKey => (
'pem',
l10n.l_export_public_key_file,
result.publicKey,
),
GenerateType.csr => (
'csr',
l10n.l_export_csr_file,
result.result,
),
_ => (null, null, null),
};
if (fileExt != null) {
final filePath = await FilePicker.platform.saveFile( final filePath = await FilePicker.platform.saveFile(
dialogTitle: l10n.l_export_csr_file, dialogTitle: title,
allowedExtensions: ['csr'], allowedExtensions: [fileExt],
type: FileType.custom, type: FileType.custom,
lockParentWindow: true, lockParentWindow: true,
); );
if (filePath != null) { if (filePath != null) {
final file = File(filePath); final file = File(filePath);
await file.writeAsString(result!.result, flush: true); await file.writeAsString(data!, flush: true);
} }
break; }
default:
break;
} }
return result != null; return result != null;
@ -250,165 +262,6 @@ class PivActions extends ConsumerWidget {
} }
} }
Widget registerPivActions(
DevicePath devicePath,
PivState pivState, {
required WidgetRef ref,
required Widget Function(BuildContext context) builder,
Map<Type, Action<Intent>> actions = const {},
}) {
final hasFeature = ref.watch(featureProvider);
return Actions(
actions: {
if (hasFeature(features.slotsGenerate))
GenerateIntent:
CallbackAction<GenerateIntent>(onInvoke: (intent) async {
final withContext = ref.read(withContextProvider);
if (!pivState.protectedKey &&
!await withContext(
(context) => _authIfNeeded(context, devicePath, pivState))) {
return false;
}
// TODO: Avoid asking for PIN if not needed?
final verified = await withContext((context) async =>
await showBlurDialog(
context: context,
builder: (context) => PinDialog(devicePath))) ??
false;
if (!verified) {
return false;
}
return await withContext((context) async {
final l10n = AppLocalizations.of(context)!;
final PivGenerateResult? result = await showBlurDialog(
context: context,
builder: (context) => GenerateKeyDialog(
devicePath,
pivState,
intent.slot,
),
);
switch (result?.generateType) {
case GenerateType.csr:
final filePath = await FilePicker.platform.saveFile(
dialogTitle: l10n.l_export_csr_file,
allowedExtensions: ['csr'],
type: FileType.custom,
lockParentWindow: true,
);
if (filePath != null) {
final file = File(filePath);
await file.writeAsString(result!.result, flush: true);
}
break;
default:
break;
}
return result != null;
});
}),
if (hasFeature(features.slotsImport))
ImportIntent: CallbackAction<ImportIntent>(onInvoke: (intent) async {
final withContext = ref.read(withContextProvider);
if (!await withContext(
(context) => _authIfNeeded(context, devicePath, pivState))) {
return false;
}
final picked = await withContext(
(context) async {
final l10n = AppLocalizations.of(context)!;
return await FilePicker.platform.pickFiles(
allowedExtensions: ['pem', 'der', 'pfx', 'p12', 'key', 'crt'],
type: FileType.custom,
allowMultiple: false,
lockParentWindow: true,
dialogTitle: l10n.l_select_import_file);
},
);
if (picked == null || picked.files.isEmpty) {
return false;
}
return await withContext((context) async =>
await showBlurDialog(
context: context,
builder: (context) => ImportFileDialog(
devicePath,
pivState,
intent.slot,
File(picked.paths.first!),
),
) ??
false);
}),
if (hasFeature(features.slotsExport))
ExportIntent: CallbackAction<ExportIntent>(onInvoke: (intent) async {
final (_, cert) = await ref
.read(pivSlotsProvider(devicePath).notifier)
.read(intent.slot.slot);
if (cert == null) {
return false;
}
final withContext = ref.read(withContextProvider);
final filePath = await withContext((context) async {
final l10n = AppLocalizations.of(context)!;
return await FilePicker.platform.saveFile(
dialogTitle: l10n.l_export_certificate_file,
allowedExtensions: ['pem'],
type: FileType.custom,
lockParentWindow: true,
);
});
if (filePath == null) {
return false;
}
final file = File(filePath);
await file.writeAsString(cert, flush: true);
await withContext((context) async {
final l10n = AppLocalizations.of(context)!;
showMessage(context, l10n.l_certificate_exported);
});
return true;
}),
if (hasFeature(features.slotsDelete))
DeleteIntent<PivSlot>:
CallbackAction<DeleteIntent<PivSlot>>(onInvoke: (intent) async {
final withContext = ref.read(withContextProvider);
if (!await withContext(
(context) => _authIfNeeded(context, devicePath, pivState))) {
return false;
}
final bool? deleted = await withContext((context) async =>
await showBlurDialog(
context: context,
builder: (context) => DeleteCertificateDialog(
devicePath,
intent.target,
),
) ??
false);
return deleted;
}),
...actions,
},
child: Builder(builder: builder),
);
}
List<ActionItem> buildSlotActions(PivSlot slot, AppLocalizations l10n) { List<ActionItem> buildSlotActions(PivSlot slot, AppLocalizations l10n) {
final hasCert = slot.certInfo != null; final hasCert = slot.certInfo != null;
return [ return [

View File

@ -22,13 +22,13 @@ import 'package:intl/intl.dart';
import '../../app/message.dart'; import '../../app/message.dart';
import '../../app/state.dart'; import '../../app/state.dart';
import '../../widgets/tooltip_if_truncated.dart'; import '../../widgets/tooltip_if_truncated.dart';
import '../keys.dart'; import '../keys.dart' as keys;
import '../models.dart'; import '../models.dart';
class CertInfoTable extends ConsumerWidget { class _InfoTable extends ConsumerWidget {
final CertInfo certInfo; final Map<String, (String, Key)> values;
const CertInfoTable(this.certInfo, {super.key}); const _InfoTable(this.values);
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
@ -38,70 +38,96 @@ class CertInfoTable extends ConsumerWidget {
final subtitleStyle = textTheme.bodyMedium!.copyWith( final subtitleStyle = textTheme.bodyMedium!.copyWith(
color: Theme.of(context).colorScheme.onSurfaceVariant, color: Theme.of(context).colorScheme.onSurfaceVariant,
); );
final dateFormat =
DateFormat.yMMMEd(ref.watch(currentLocaleProvider).toString());
final clipboard = ref.watch(clipboardProvider); final clipboard = ref.watch(clipboardProvider);
final withContext = ref.watch(withContextProvider); final withContext = ref.watch(withContextProvider);
Widget header(String title) => Text(
title,
textAlign: TextAlign.right,
);
Widget body(String title, String value, Key key) => GestureDetector(
onDoubleTap: () async {
await clipboard.setText(value);
if (!clipboard.platformGivesFeedback()) {
await withContext((context) async {
showMessage(context, l10n.p_target_copied_clipboard(title));
});
}
},
child: TooltipIfTruncated(
key: key,
text: value,
style: subtitleStyle,
tooltip: value.replaceAllMapped(
RegExp(r',([A-Z]+)='), (match) => '\n${match[1]}='),
),
);
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Column( Column(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: values.keys
header(l10n.s_subject), .map((title) => Text(
header(l10n.s_issuer), title,
header(l10n.s_serial), textAlign: TextAlign.right,
header(l10n.s_certificate_fingerprint), ))
header(l10n.s_valid_from), .toList(),
header(l10n.s_valid_to),
],
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Flexible( Flexible(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: values.entries.map((e) {
body(l10n.s_subject, certInfo.subject, certInfoSubjectKey), final title = e.key;
body(l10n.s_issuer, certInfo.issuer, certInfoIssuerKey), final (value, key) = e.value;
body(l10n.s_serial, certInfo.serial, certInfoSerialKey), return GestureDetector(
body(l10n.s_certificate_fingerprint, certInfo.fingerprint, onDoubleTap: () async {
certInfoFingerprintKey), await clipboard.setText(value);
body( if (!clipboard.platformGivesFeedback()) {
l10n.s_valid_from, await withContext((context) async {
dateFormat.format(DateTime.parse(certInfo.notValidBefore)), showMessage(
certInfoValidFromKey), context, l10n.p_target_copied_clipboard(title));
body( });
l10n.s_valid_to, }
dateFormat.format(DateTime.parse(certInfo.notValidAfter)), },
certInfoValidToKey), child: TooltipIfTruncated(
], key: key,
text: value,
style: subtitleStyle,
tooltip: value.replaceAllMapped(
RegExp(r',([A-Z]+)='), (match) => '\n${match[1]}='),
),
);
}).toList(),
), ),
), ),
], ],
); );
} }
} }
class CertInfoTable extends ConsumerWidget {
final CertInfo? certInfo;
final SlotMetadata? metadata;
const CertInfoTable(this.certInfo, this.metadata, {super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final l10n = AppLocalizations.of(context)!;
final dateFormat =
DateFormat.yMMMEd(ref.watch(currentLocaleProvider).toString());
final certInfo = this.certInfo;
final metadata = this.metadata;
return _InfoTable({
if (metadata != null)
l10n.s_private_key: (
metadata.keyType.getDisplayName(l10n),
keys.slotMetadataKeyType
),
if (certInfo != null) ...{
l10n.s_public_key: (
certInfo.keyType?.getDisplayName(l10n) ?? l10n.s_unknown_type,
keys.certInfoKeyType
),
l10n.s_subject: (certInfo.subject, keys.certInfoSubject),
l10n.s_issuer: (certInfo.issuer, keys.certInfoIssuer),
l10n.s_serial: (certInfo.serial, keys.certInfoSerial),
l10n.s_certificate_fingerprint: (
certInfo.fingerprint,
keys.certInfoFingerprint
),
l10n.s_valid_from: (
dateFormat.format(DateTime.parse(certInfo.notValidBefore)),
keys.certInfoValidFrom
),
l10n.s_valid_to: (
dateFormat.format(DateTime.parse(certInfo.notValidAfter)),
keys.certInfoValidTo
),
},
});
}
}

View File

@ -65,13 +65,14 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
_validToMax = DateTime.utc(now.year + 10, now.month, now.day); _validToMax = DateTime.utc(now.year + 10, now.month, now.day);
} }
List<KeyType> _getSupportedKeyTypes() => [ List<KeyType> _getSupportedKeyTypes(bool isFips) => [
KeyType.rsa1024, if (!isFips) KeyType.rsa1024,
KeyType.rsa2048, KeyType.rsa2048,
if (widget.pivState.version.isAtLeast(5, 7)) ...[ if (widget.pivState.version.isAtLeast(5, 7)) ...[
KeyType.rsa3072, KeyType.rsa3072,
KeyType.rsa4096, KeyType.rsa4096,
KeyType.ed25519, KeyType.ed25519,
if (!isFips) KeyType.x25519,
], ],
KeyType.eccp256, KeyType.eccp256,
KeyType.eccp384, KeyType.eccp384,
@ -86,15 +87,20 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
color: Theme.of(context).colorScheme.onSurfaceVariant, color: Theme.of(context).colorScheme.onSurfaceVariant,
); );
final isFips =
ref.watch(currentDeviceDataProvider).valueOrNull?.info.isFips ?? false;
final canSave = !_generating &&
(!_invalidSubject || _generateType == GenerateType.publicKey);
return ResponsiveDialog( return ResponsiveDialog(
allowCancel: !_generating, allowCancel: !_generating,
title: Text(l10n.s_generate_key), title: Text(l10n.s_generate_key),
actions: [ actions: [
TextButton( TextButton(
key: keys.saveButton, key: keys.saveButton,
onPressed: _generating || _invalidSubject onPressed: canSave
? null ? () async {
: () async {
if (!await confirmOverwrite( if (!await confirmOverwrite(
context, context,
widget.pivSlot, widget.pivSlot,
@ -111,11 +117,12 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
final pivNotifier = final pivNotifier =
ref.read(pivSlotsProvider(widget.devicePath).notifier); ref.read(pivSlotsProvider(widget.devicePath).notifier);
if (!await pivNotifier.validateRfc4514(_subject)) { if (!(_generateType == GenerateType.publicKey ||
await pivNotifier.validateRfc4514(_subject))) {
setState(() { setState(() {
_generating = false; _generating = false;
_invalidSubject = true;
}); });
_invalidSubject = true;
return; return;
} }
@ -123,6 +130,8 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
widget.pivSlot.slot, widget.pivSlot.slot,
_keyType, _keyType,
parameters: switch (_generateType) { parameters: switch (_generateType) {
GenerateType.publicKey =>
PivGenerateParameters.publicKey(),
GenerateType.certificate => GenerateType.certificate =>
PivGenerateParameters.certificate( PivGenerateParameters.certificate(
subject: _subject, subject: _subject,
@ -142,7 +151,8 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
); );
}, },
); );
}, }
: null,
child: Text(l10n.s_save), child: Text(l10n.s_save),
), ),
], ],
@ -169,7 +179,7 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
: null, : null,
), ),
textInputAction: TextInputAction.next, textInputAction: TextInputAction.next,
enabled: !_generating, enabled: !_generating && _generateType != GenerateType.publicKey,
onChanged: (value) { onChanged: (value) {
setState(() { setState(() {
_invalidSubject = value.isEmpty; _invalidSubject = value.isEmpty;
@ -192,7 +202,7 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
runSpacing: 8.0, runSpacing: 8.0,
children: [ children: [
ChoiceFilterChip<KeyType>( ChoiceFilterChip<KeyType>(
items: _getSupportedKeyTypes(), items: _getSupportedKeyTypes(isFips),
value: _keyType, value: _keyType,
selected: _keyType != defaultKeyType, selected: _keyType != defaultKeyType,
itemBuilder: (value) => Text(value.getDisplayName(l10n)), itemBuilder: (value) => Text(value.getDisplayName(l10n)),
@ -201,6 +211,9 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
: (value) { : (value) {
setState(() { setState(() {
_keyType = value; _keyType = value;
if (value == KeyType.x25519) {
_generateType = GenerateType.publicKey;
}
}); });
}, },
), ),
@ -209,7 +222,7 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
value: _generateType, value: _generateType,
selected: _generateType != defaultGenerateType, selected: _generateType != defaultGenerateType,
itemBuilder: (value) => Text(value.getDisplayName(l10n)), itemBuilder: (value) => Text(value.getDisplayName(l10n)),
onChanged: _generating onChanged: _generating || _keyType == KeyType.x25519
? null ? null
: (value) { : (value) {
setState(() { setState(() {

View File

@ -256,7 +256,7 @@ class _ImportFileDialogState extends ConsumerState<ImportFileDialog> {
), ),
SizedBox( SizedBox(
height: 120, // Needed for layout, adapt if text sizes changes height: 120, // Needed for layout, adapt if text sizes changes
child: CertInfoTable(certInfo), child: CertInfoTable(certInfo, null),
), ),
] ]
] ]

View File

@ -68,7 +68,7 @@ Future<bool> confirmOverwrite(
required bool writeCert, required bool writeCert,
}) async { }) async {
final overwritesCert = writeCert && pivSlot.certInfo != null; final overwritesCert = writeCert && pivSlot.certInfo != null;
final overwritesKey = writeKey ? pivSlot.hasKey : false; final overwritesKey = writeKey ? pivSlot.metadata != null : false;
if (overwritesCert || overwritesKey != false) { if (overwritesCert || overwritesKey != false) {
return await showBlurDialog( return await showBlurDialog(
context: context, context: context,

View File

@ -128,14 +128,19 @@ class _PivScreenState extends ConsumerState<PivScreen> {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
selected.certInfo != null if (selected.certInfo != null ||
? CertInfoTable(selected.certInfo!) selected.metadata != null) ...[
: Text( CertInfoTable(selected.certInfo,
l10n.l_no_certificate, selected.metadata),
softWrap: true, const SizedBox(height: 16),
textAlign: TextAlign.center, ],
style: subtitleStyle, if (selected.certInfo == null)
), Text(
l10n.l_no_certificate,
softWrap: true,
textAlign: TextAlign.center,
style: subtitleStyle,
),
], ],
), ),
), ),
@ -225,7 +230,7 @@ class _CertificateListItem extends ConsumerWidget {
subtitle: certInfo != null subtitle: certInfo != null
// Simplify subtitle by stripping "CN=", etc. // Simplify subtitle by stripping "CN=", etc.
? certInfo.subject.replaceAll(RegExp(r'[A-Z]+='), ' ').trimLeft() ? certInfo.subject.replaceAll(RegExp(r'[A-Z]+='), ' ').trimLeft()
: pivSlot.hasKey == true : pivSlot.metadata != null
? l10n.l_key_no_certificate ? l10n.l_key_no_certificate
: l10n.l_no_certificate, : l10n.l_no_certificate,
trailing: expanded trailing: expanded

View File

@ -59,6 +59,7 @@ class SlotDialog extends ConsumerWidget {
} }
final certInfo = slotData.certInfo; final certInfo = slotData.certInfo;
final metadata = slotData.metadata;
return PivActions( return PivActions(
devicePath: node.path, devicePath: node.path,
pivState: pivState, pivState: pivState,
@ -79,26 +80,34 @@ class SlotDialog extends ConsumerWidget {
softWrap: true, softWrap: true,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
if (certInfo != null) ...[ Padding(
Padding( padding: const EdgeInsets.all(16),
padding: const EdgeInsets.all(16), child: Column(
child: CertInfoTable(certInfo), children: [
if (certInfo != null || metadata != null) ...[
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: CertInfoTable(certInfo, metadata),
),
],
if (certInfo == null) ...[
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: Text(
l10n.l_no_certificate,
softWrap: true,
textAlign: TextAlign.center,
style: subtitleStyle,
),
),
],
],
), ),
] else ...[ ),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Text(
l10n.l_no_certificate,
softWrap: true,
textAlign: TextAlign.center,
style: subtitleStyle,
),
),
const SizedBox(height: 16),
],
], ],
), ),
), ),
const SizedBox(height: 16),
ActionListSection.fromMenuActions( ActionListSection.fromMenuActions(
context, context,
l10n.s_actions, l10n.s_actions,