mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-25 23:14:18 +03:00
367 lines
8.6 KiB
Dart
367 lines
8.6 KiB
Dart
/*
|
|
* Copyright (C) 2023 Yubico.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
|
|
import '../core/models.dart';
|
|
|
|
part 'models.freezed.dart';
|
|
part 'models.g.dart';
|
|
|
|
const defaultManagementKey = '010203040506070801020304050607080102030405060708';
|
|
const defaultManagementKeyType = ManagementKeyType.tdes;
|
|
const defaultKeyType = KeyType.eccp256;
|
|
const defaultGenerateType = GenerateType.certificate;
|
|
const defaultPin = '123456';
|
|
const defaultPuk = '12345678';
|
|
|
|
enum GenerateType {
|
|
publicKey,
|
|
certificate,
|
|
csr;
|
|
|
|
String getDisplayName(AppLocalizations l10n) {
|
|
return switch (this) {
|
|
GenerateType.publicKey => l10n.s_public_key,
|
|
GenerateType.certificate => l10n.s_certificate,
|
|
GenerateType.csr => l10n.s_csr,
|
|
};
|
|
}
|
|
}
|
|
|
|
enum SlotId {
|
|
authentication(0x9a),
|
|
signature(0x9c),
|
|
keyManagement(0x9d),
|
|
cardAuth(0x9e),
|
|
retired1(0x82, true),
|
|
retired2(0x83, true),
|
|
retired3(0x84, true),
|
|
retired4(0x85, true),
|
|
retired5(0x86, true),
|
|
retired6(0x87, true),
|
|
retired7(0x88, true),
|
|
retired8(0x89, true),
|
|
retired9(0x8a, true),
|
|
retired10(0x8b, true),
|
|
retired11(0x8c, true),
|
|
retired12(0x8d, true),
|
|
retired13(0x8e, true),
|
|
retired14(0x8f, true),
|
|
retired15(0x90, true),
|
|
retired16(0x91, true),
|
|
retired17(0x92, true),
|
|
retired18(0x93, true),
|
|
retired19(0x94, true),
|
|
retired20(0x95, true);
|
|
|
|
final int id;
|
|
final bool isRetired;
|
|
const SlotId(this.id, [this.isRetired = false]);
|
|
|
|
String get hexId => id.toRadixString(16).padLeft(2, '0');
|
|
|
|
String getSlotName(AppLocalizations l10n) {
|
|
return switch (this) {
|
|
SlotId.authentication => l10n.s_slot_9a,
|
|
SlotId.signature => l10n.s_slot_9c,
|
|
SlotId.keyManagement => l10n.s_slot_9d,
|
|
SlotId.cardAuth => l10n.s_slot_9e,
|
|
_ => l10n.s_retired_slot
|
|
};
|
|
}
|
|
|
|
String getDisplayName(AppLocalizations l10n) {
|
|
return l10n.s_slot_display_name(getSlotName(l10n), hexId);
|
|
}
|
|
|
|
factory SlotId.fromJson(int value) =>
|
|
SlotId.values.firstWhere((e) => e.id == value);
|
|
}
|
|
|
|
@JsonEnum(alwaysCreate: true)
|
|
enum PinPolicy {
|
|
@JsonValue(0x00)
|
|
dfault,
|
|
@JsonValue(0x01)
|
|
never,
|
|
@JsonValue(0x02)
|
|
once,
|
|
@JsonValue(0x03)
|
|
always,
|
|
@JsonValue(0x04)
|
|
matchOnce,
|
|
@JsonValue(0x05)
|
|
matchAlways;
|
|
|
|
const PinPolicy();
|
|
|
|
int get value => _$PinPolicyEnumMap[this]!;
|
|
|
|
String getDisplayName(AppLocalizations l10n) {
|
|
return switch (this) {
|
|
// TODO:
|
|
_ => name
|
|
};
|
|
}
|
|
}
|
|
|
|
@JsonEnum(alwaysCreate: true)
|
|
enum TouchPolicy {
|
|
@JsonValue(0x00)
|
|
dfault,
|
|
@JsonValue(0x01)
|
|
never,
|
|
@JsonValue(0x02)
|
|
always,
|
|
@JsonValue(0x03)
|
|
cached;
|
|
|
|
const TouchPolicy();
|
|
|
|
int get value => _$TouchPolicyEnumMap[this]!;
|
|
|
|
String getDisplayName(AppLocalizations l10n) {
|
|
return switch (this) {
|
|
// TODO:
|
|
_ => name
|
|
};
|
|
}
|
|
}
|
|
|
|
@JsonEnum(alwaysCreate: true)
|
|
enum KeyType {
|
|
@JsonValue(0x06)
|
|
rsa1024,
|
|
@JsonValue(0x07)
|
|
rsa2048,
|
|
@JsonValue(0x05)
|
|
rsa3072,
|
|
@JsonValue(0x16)
|
|
rsa4096,
|
|
@JsonValue(0x11)
|
|
eccp256,
|
|
@JsonValue(0x14)
|
|
eccp384,
|
|
@JsonValue(0xe0)
|
|
ed25519,
|
|
@JsonValue(0xe1)
|
|
x25519;
|
|
|
|
const KeyType();
|
|
|
|
int get value => _$KeyTypeEnumMap[this]!;
|
|
|
|
String getDisplayName(AppLocalizations l10n) {
|
|
return switch (this) {
|
|
// TODO: Should these be translatable?
|
|
_ => name.toUpperCase()
|
|
};
|
|
}
|
|
}
|
|
|
|
enum ManagementKeyType {
|
|
@JsonValue(0x03)
|
|
tdes(24),
|
|
@JsonValue(0x08)
|
|
aes128(16),
|
|
@JsonValue(0x0A)
|
|
aes192(24),
|
|
@JsonValue(0x0C)
|
|
aes256(32);
|
|
|
|
const ManagementKeyType(this.keyLength);
|
|
final int keyLength;
|
|
|
|
int get value => _$ManagementKeyTypeEnumMap[this]!;
|
|
|
|
String getDisplayName(AppLocalizations l10n) {
|
|
return switch (this) {
|
|
// TODO: Should these be translatable?
|
|
_ => name.toUpperCase()
|
|
};
|
|
}
|
|
}
|
|
|
|
@freezed
|
|
class PinMetadata with _$PinMetadata {
|
|
factory PinMetadata(
|
|
bool defaultValue,
|
|
int totalAttempts,
|
|
int attemptsRemaining,
|
|
) = _PinMetadata;
|
|
|
|
factory PinMetadata.fromJson(Map<String, dynamic> json) =>
|
|
_$PinMetadataFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PinVerificationStatus with _$PinVerificationStatus {
|
|
const factory PinVerificationStatus.success() = PinSuccess;
|
|
factory PinVerificationStatus.failure(PivPinFailureReason reason) =
|
|
PinFailure;
|
|
}
|
|
|
|
@freezed
|
|
class PivPinFailureReason with _$PivPinFailureReason {
|
|
factory PivPinFailureReason.invalidPin(int attemptsRemaining) = PivInvalidPin;
|
|
const factory PivPinFailureReason.weakPin() = PivWeakPin;
|
|
}
|
|
|
|
@freezed
|
|
class ManagementKeyMetadata with _$ManagementKeyMetadata {
|
|
factory ManagementKeyMetadata(
|
|
ManagementKeyType keyType,
|
|
bool defaultValue,
|
|
TouchPolicy touchPolicy,
|
|
) = _ManagementKeyMetadata;
|
|
|
|
factory ManagementKeyMetadata.fromJson(Map<String, dynamic> json) =>
|
|
_$ManagementKeyMetadataFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class SlotMetadata with _$SlotMetadata {
|
|
factory SlotMetadata(
|
|
KeyType keyType,
|
|
PinPolicy pinPolicy,
|
|
TouchPolicy touchPolicy,
|
|
bool generated,
|
|
String publicKey,
|
|
) = _SlotMetadata;
|
|
|
|
factory SlotMetadata.fromJson(Map<String, dynamic> json) =>
|
|
_$SlotMetadataFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PivStateMetadata with _$PivStateMetadata {
|
|
factory PivStateMetadata({
|
|
required ManagementKeyMetadata managementKeyMetadata,
|
|
required PinMetadata pinMetadata,
|
|
required PinMetadata pukMetadata,
|
|
}) = _PivStateMetadata;
|
|
|
|
factory PivStateMetadata.fromJson(Map<String, dynamic> json) =>
|
|
_$PivStateMetadataFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PivState with _$PivState {
|
|
const PivState._();
|
|
|
|
factory PivState({
|
|
required Version version,
|
|
required bool authenticated,
|
|
required bool derivedKey,
|
|
required bool storedKey,
|
|
required int pinAttempts,
|
|
required bool supportsBio,
|
|
String? chuid,
|
|
String? ccc,
|
|
PivStateMetadata? metadata,
|
|
}) = _PivState;
|
|
|
|
bool get protectedKey => derivedKey || storedKey;
|
|
bool get needsAuth =>
|
|
!authenticated && metadata?.managementKeyMetadata.defaultValue != true;
|
|
bool get supportsMetadata => version.isAtLeast(5, 3);
|
|
|
|
factory PivState.fromJson(Map<String, dynamic> json) =>
|
|
_$PivStateFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class CertInfo with _$CertInfo {
|
|
factory CertInfo({
|
|
required KeyType? keyType,
|
|
required String subject,
|
|
required String issuer,
|
|
required String serial,
|
|
required String notValidBefore,
|
|
required String notValidAfter,
|
|
required String fingerprint,
|
|
}) = _CertInfo;
|
|
|
|
factory CertInfo.fromJson(Map<String, dynamic> json) =>
|
|
_$CertInfoFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PivSlot with _$PivSlot {
|
|
factory PivSlot({
|
|
required SlotId slot,
|
|
SlotMetadata? metadata,
|
|
CertInfo? certInfo,
|
|
}) = _PivSlot;
|
|
|
|
factory PivSlot.fromJson(Map<String, dynamic> json) =>
|
|
_$PivSlotFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PivExamineResult with _$PivExamineResult {
|
|
factory PivExamineResult.result({
|
|
required bool password,
|
|
required KeyType? keyType,
|
|
required CertInfo? certInfo,
|
|
}) = _ExamineResult;
|
|
factory PivExamineResult.invalidPassword() = _InvalidPassword;
|
|
|
|
factory PivExamineResult.fromJson(Map<String, dynamic> json) =>
|
|
_$PivExamineResultFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PivGenerateParameters with _$PivGenerateParameters {
|
|
factory PivGenerateParameters.publicKey() = _GeneratePublicKey;
|
|
|
|
factory PivGenerateParameters.certificate({
|
|
required String subject,
|
|
required DateTime validFrom,
|
|
required DateTime validTo,
|
|
}) = _GenerateCertificate;
|
|
|
|
factory PivGenerateParameters.csr({
|
|
required String subject,
|
|
}) = _GenerateCsr;
|
|
}
|
|
|
|
@freezed
|
|
class PivGenerateResult with _$PivGenerateResult {
|
|
factory PivGenerateResult({
|
|
required GenerateType generateType,
|
|
required String publicKey,
|
|
String? result,
|
|
}) = _PivGenerateResult;
|
|
|
|
factory PivGenerateResult.fromJson(Map<String, dynamic> json) =>
|
|
_$PivGenerateResultFromJson(json);
|
|
}
|
|
|
|
@freezed
|
|
class PivImportResult with _$PivImportResult {
|
|
factory PivImportResult({
|
|
required SlotMetadata? metadata,
|
|
required String? publicKey,
|
|
required String? certificate,
|
|
}) = _PivImportResult;
|
|
|
|
factory PivImportResult.fromJson(Map<String, dynamic> json) =>
|
|
_$PivImportResultFromJson(json);
|
|
}
|