Skip to content

Commit

Permalink
IOS-3291 Merge branch 'develop' into IOS-3291_get_entropy
Browse files Browse the repository at this point in the history
  • Loading branch information
tureck1y committed Apr 4, 2023
2 parents 358ee5b + d2c3e00 commit d13821e
Show file tree
Hide file tree
Showing 29 changed files with 356 additions and 47 deletions.
25 changes: 24 additions & 1 deletion Example/TangemSdkExample/AppModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class AppModel: ObservableObject {

//Wallet creation
@Published var curve: EllipticCurve = .secp256k1
@Published var mnemonicString: String = ""
//Sign
@Published var derivationPath: String = ""
//Attestation
Expand Down Expand Up @@ -285,11 +286,31 @@ extension AppModel {
self.complete(with: "Scan card to retrieve cardId")
return
}

tangemSdk.createWallet(curve: curve,
cardId: cardId,
completion: handleCompletion)
}

func importWallet() {
guard let cardId = card?.cardId else {
self.complete(with: "Scan card to retrieve cardId")
return
}

do {
let mnemonic = try Mnemonic(with: mnemonicString)
let seed = try mnemonic.generateSeed()

tangemSdk.importWallet(curve: curve,
cardId: cardId,
seed: seed,
completion: handleCompletion)
}
catch {
self.complete(with: error)
}
}

func purgeWallet(walletPublicKey: Data) {
guard let cardId = card?.cardId else {
Expand Down Expand Up @@ -656,6 +677,7 @@ extension AppModel {
case setPasscode
case resetUserCodes
case createWallet
case importWallet
case purgeWallet
//files
case readFiles
Expand Down Expand Up @@ -693,6 +715,7 @@ extension AppModel {
case .signHash: runWithPublicKey(signHash, walletPublicKey)
case .signHashes: runWithPublicKey(signHashes, walletPublicKey)
case .createWallet: createWallet()
case .importWallet: importWallet()
case .purgeWallet: runWithPublicKey(purgeWallet, walletPublicKey)
case .readFiles: readFiles()
case .writeUserFile: writeUserFile()
Expand Down
8 changes: 7 additions & 1 deletion Example/TangemSdkExample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ struct ContentView: View {
.cornerRadius(8)
.overlay(RoundedRectangle(cornerRadius: 8)
.stroke(Color.orange, lineWidth: 2))
case .createWallet:
case .createWallet, .importWallet:
VStack {
Text("Create wallet configuration")
.font(.headline)
Expand All @@ -140,6 +140,12 @@ struct ContentView: View {
}
.pickerStyle(SegmentedPickerStyle())
}

if case .importWallet = model.method {
TextField("Optional mnemonic", text: $model.mnemonicString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.autocapitalization(.none)
}
}
.padding()
.cornerRadius(8)
Expand Down
1 change: 1 addition & 0 deletions Example/TangemSdkExample/Developer/StaticData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ extension AppModel {
"disableFiles": false,
"allowHDWallets": true,
"allowBackup": true,
"allowKeysImport": true,
"NDEF": [],
"cardData": {
"date": "2021-03-15",
Expand Down
4 changes: 4 additions & 0 deletions TangemSdk/TangemSdk.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@
DC59CB0E29AF70C700EC14E1 /* Mnemonic.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC59CB0D29AF70C700EC14E1 /* Mnemonic.swift */; };
DC8B0E3F286F221D009D64F7 /* BiometricsUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC8B0E3E286F221D009D64F7 /* BiometricsUtil.swift */; };
DCA9706628E35EAD0046E62E /* GenerateOTPCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCA9706528E35EAD0046E62E /* GenerateOTPCommand.swift */; };
DCE3281729D5DEE500AAC4AC /* ImportWallet.json in Resources */ = {isa = PBXBuildFile; fileRef = DCE3281629D5DEE500AAC4AC /* ImportWallet.json */; };
DCC6A64829D212E8007BA5B7 /* GetEntropyCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC6A64729D212E8007BA5B7 /* GetEntropyCommand.swift */; };
DCEA3ABC2875AEBA00B0B0DA /* BiometricsStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCEA3ABB2875AEBA00B0B0DA /* BiometricsStorage.swift */; };
DCEA3ABE2875AF0F00B0B0DA /* SecureStorageKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCEA3ABD2875AF0F00B0B0DA /* SecureStorageKey.swift */; };
Expand Down Expand Up @@ -655,6 +656,7 @@
DC8B0E3E286F221D009D64F7 /* BiometricsUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BiometricsUtil.swift; sourceTree = "<group>"; };
DCA9706528E35EAD0046E62E /* GenerateOTPCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateOTPCommand.swift; sourceTree = "<group>"; };
DCC6A64729D212E8007BA5B7 /* GetEntropyCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetEntropyCommand.swift; sourceTree = "<group>"; };
DCE3281629D5DEE500AAC4AC /* ImportWallet.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ImportWallet.json; sourceTree = "<group>"; };
DCEA3ABB2875AEBA00B0B0DA /* BiometricsStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BiometricsStorage.swift; sourceTree = "<group>"; };
DCEA3ABD2875AF0F00B0B0DA /* SecureStorageKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureStorageKey.swift; sourceTree = "<group>"; };
DCFCA17628F5629F0037586C /* FocusableTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusableTextField.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -836,6 +838,7 @@
5D54408D268226B600F7D05B /* Depersonalize.json */,
5D54408F268226BC00F7D05B /* PurgeWallet.json */,
5D5440912682297A00F7D05B /* CreateWallet.json */,
DCE3281629D5DEE500AAC4AC /* ImportWallet.json */,
5D544093268243F700F7D05B /* Card.json */,
);
path = Jsons;
Expand Down Expand Up @@ -1663,6 +1666,7 @@
5D2BDF8626DD4869002F7E19 /* TestParseRequest.json in Resources */,
DC1244C329B766B70037BC05 /* mnemonic_valid_test_vectors.json in Resources */,
5D5440922682297A00F7D05B /* CreateWallet.json in Resources */,
DCE3281729D5DEE500AAC4AC /* ImportWallet.json in Resources */,
5D54408C2682269400F7D05B /* SetPasscode.json in Resources */,
5D4B127D26D3D351006E173C /* WriteFiles.json in Resources */,
);
Expand Down
3 changes: 3 additions & 0 deletions TangemSdk/TangemSdk/Common/APDU/StatusWord.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum StatusWord: UInt16 {
case walletNotFound = 0x6A88
case invalidAccessCode = 0x6AF1
case invalidPascode = 0x6AF2
case walletAlreadyExists = 0x6A89
//case pinsNotChanged = 0x9000 //equal to processCompleted

func toTangemSdkError() -> TangemSdkError? {
Expand All @@ -54,6 +55,8 @@ public enum StatusWord: UInt16 {
return TangemSdkError.accessCodeRequired
case .invalidPascode:
return TangemSdkError.passcodeRequired
case .walletAlreadyExists:
return TangemSdkError.walletAlreadyCreated
default:
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions TangemSdk/TangemSdk/Common/Card/CardSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public extension Card {
public let isHDWalletAllowed: Bool
/// Is allowed to create backup
public let isBackupAllowed: Bool
/// Is allowed to import keys. COS. v6.11+
public let isKeysImportAllowed: Bool
/// Is allowed to delete wallet. COS before v4
@SkipEncoding
var isPermanentWallet: Bool
Expand Down Expand Up @@ -71,6 +73,7 @@ extension Card.Settings {
self.isHDWalletAllowed = mask.contains(.allowHDWallets)
self.isFilesAllowed = !mask.contains(.disableFiles)
self.isBackupAllowed = mask.contains(.allowBackup)
self.isKeysImportAllowed = mask.contains(.allowKeysImport)

var encryptionModes: [EncryptionMode] = [.strong]
if mask.contains(.allowFastEncryption) {
Expand Down Expand Up @@ -145,6 +148,7 @@ extension CardSettingsMask {
static let isReusable = CardSettingsMask(rawValue: 0x0001)
static let allowHDWallets = CardSettingsMask(rawValue: 0x00200000)
static let allowBackup = CardSettingsMask(rawValue: 0x00400000)
static let allowKeysImport = CardSettingsMask(rawValue: 0x00800000)
}

//MARK:- CardSettingsMask OptionSetCodable conformance
Expand Down
2 changes: 2 additions & 0 deletions TangemSdk/TangemSdk/Common/Card/FirmwareVersion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ public extension FirmwareVersion { //todo: move all doubleValue checks to consta
static let backupAvailable = FirmwareVersion(major: 4, minor: 39)
/// Wallet ownership confirmation available
static let walletOwnershipConfirmationAvailable = FirmwareVersion(major: 2, minor: 1)
/// Keys import support
static let keysImportAvailable = FirmwareVersion(major: 6, minor: 11)
/// Tmp range for visa cards
static let visaRange = 5.25...5.30
}
Expand Down
44 changes: 40 additions & 4 deletions TangemSdk/TangemSdk/Common/Card/Wallet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public extension Card {
public let index: Int
/// Proof for BLS Proof of possession scheme (POP)
public let proof: Data?
/// Has this key been imported to a card. E.g. from seed phrase
public let isImported: Bool
/// Does this wallet has a backup
public var hasBackup: Bool
/// Derived keys according to `Config.defaultDerivationPaths`
Expand All @@ -46,19 +48,53 @@ public extension Card.Wallet {
}

@available(iOS 13.0, *)
extension Card.Wallet {
public extension Card.Wallet {
/// Status of the wallet.
enum Status: Int, StatusType { //TODO: Specify
enum Status: Int, StatusType, JSONStringConvertible { //TODO: Specify
/// Wallet not created
case empty = 1
/// Wallet created and can be used for signing
case loaded = 2
/// Wallet was purged and can't be recreated or used for signing
case purged = 3
/// Wallet created and can be used for signing, backup data read
case backuped = 0x82
case backedUp = 0x82
/// Wallet was purged and can't be recreated or used for signing, but backup data read and wallet can be usable on backup card
case backupedAndPurged = 0x83
case backedUpAndPurged = 0x83
/// Wallet was imported
case imported = 0x42
/// Wallet was imported and backed up
case backedUpImported = 0xC2
}
}

@available(iOS 13.0, *)
extension Card.Wallet.Status {
var isBackedUp: Bool {
switch self {
case .backedUp, .backedUpAndPurged, .backedUpImported:
return true
default:
return false
}
}

var isImported: Bool {
switch self {
case .imported, .backedUpImported:
return true
default:
return false
}
}

var isAvailable: Bool {
switch self {
case .empty, .purged, .backedUpAndPurged:
return false
default:
return true
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion TangemSdk/TangemSdk/Common/Core/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public struct Config {
public var cardIdDisplayFormat: CardIdDisplayFormat = .full

/// Logger configuration
public var logConfig: Log.Config = .debug
public var logConfig: Log.Config = .default

/// ScanTask or scanCard method in TangemSdk class will use this mode to attest the card
public var attestationMode: AttestationTask.Mode = .normal
Expand Down
8 changes: 6 additions & 2 deletions TangemSdk/TangemSdk/Common/Core/TangemSdkError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ public enum TangemSdkError: Error, LocalizedError, Encodable {
case walletNotFound
case cardWithMaxZeroWallets
case walletCannotBeCreated
case walletAlreadyCreated

// MARK: Backup errors
case backupFailedCardNotLinked
Expand All @@ -264,7 +265,7 @@ public enum TangemSdkError: Error, LocalizedError, Encodable {
case issuerSignatureLoadingFailed
case accessCodeOrPasscodeRequired
case noActiveBackup
case resetBackupFailedHasBackupedWallets
case resetBackupFailedHasBackedUpWallets
case backupServiceInvalidState
case noBackupCardForIndex
case emptyBackupCards
Expand All @@ -278,6 +279,7 @@ public enum TangemSdkError: Error, LocalizedError, Encodable {
//MARK: Settings
case filesDisabled
case hdWalletDisabled
case keysImportDisabled

case resetPinNoCardToReset
case resetPinWrongCard(internalCode: Int? = nil)
Expand Down Expand Up @@ -343,6 +345,7 @@ public enum TangemSdkError: Error, LocalizedError, Encodable {
case .accessCodeRequired: return 40401
case .walletCannotBeCreated: return 40403
case .cardWithMaxZeroWallets: return 40404
case .walletAlreadyCreated: return 40405

case .alreadyCreated: return 40501
case .unsupportedCurve: return 40502
Expand Down Expand Up @@ -379,7 +382,7 @@ public enum TangemSdkError: Error, LocalizedError, Encodable {
case .certificateSignatureRequired: return 41211
case .accessCodeOrPasscodeRequired: return 41212
case .noActiveBackup: return 41220
case .resetBackupFailedHasBackupedWallets: return 41221
case .resetBackupFailedHasBackedUpWallets: return 41221
case .backupServiceInvalidState: return 41222
case .noBackupCardForIndex: return 41223
case .emptyBackupCards: return 41224
Expand All @@ -399,6 +402,7 @@ public enum TangemSdkError: Error, LocalizedError, Encodable {

case .filesDisabled: return 42002
case .hdWalletDisabled: return 42003
case .keysImportDisabled: return 42004

// MARK: 5xxxx Errors
// SDK error. Errors, that occurred in the upper level of SDK, like device restrictions, user canceled the operation or SDK is busy and can’t open the new session right now.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct CardDeserializer {
remainingSignatures: remainingSignatures,
index: 0,
proof: nil,
isImported: false,
hasBackup: false)

wallets.append(wallet)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class WalletDeserializer {

func deserializeWallet(from decoder: TlvDecoder) throws -> Card.Wallet {
let status: Card.Wallet.Status = try decoder.decode(.status)
guard status == .loaded || status == .backuped else { //We need only loaded wallets

if !status.isAvailable {
throw TangemSdkError.walletNotFound
}

Expand All @@ -64,6 +65,7 @@ class WalletDeserializer {
remainingSignatures: nil,
index: try decoder.decode(.walletIndex),
proof: try decoder.decode(.proof),
hasBackup: status == .backuped)
isImported: status.isImported,
hasBackup: status.isBackedUp)
}
}
14 changes: 13 additions & 1 deletion TangemSdk/TangemSdk/Common/JSON/Handlers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,26 @@ class SignHashHandler: JSONRPCHandler {
@available(iOS 13.0, *)
class CreateWalletHandler: JSONRPCHandler {
var method: String { "CREATE_WALLET" }

func makeRunnable(from parameters: [String : Any]) throws -> AnyJSONRPCRunnable {
let curve: EllipticCurve = try parameters.value(for: "curve")
let command = CreateWalletTask(curve: curve)
return command.eraseToAnyRunnable()
}
}

@available(iOS 13.0, *)
class ImportWalletHandler: JSONRPCHandler {
var method: String { "IMPORT_WALLET" }

func makeRunnable(from parameters: [String : Any]) throws -> AnyJSONRPCRunnable {
let curve: EllipticCurve = try parameters.value(for: "curve")
let seed: Data = try parameters.value(for: "seed")
let command = CreateWalletTask(curve: curve, seed: seed)
return command.eraseToAnyRunnable()
}
}

@available(iOS 13.0, *)
class PurgeWalletHandler: JSONRPCHandler {
var method: String { "PURGE_WALLET" }
Expand Down
1 change: 1 addition & 0 deletions TangemSdk/TangemSdk/Common/JSON/JSONRPC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public final class JSONRPCConverter {
converter.register(ChangeFileSettingsHandler())
converter.register(DeriveWalletPublicKeyHandler())
converter.register(DeriveWalletPublicKeysHandler())
converter.register(ImportWalletHandler())
return converter
}()

Expand Down
10 changes: 7 additions & 3 deletions TangemSdk/TangemSdk/Common/Log/Log.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,18 @@ import Foundation
private let logger = Log()

public class Log {
public static var config: Log.Config = .verbose {
public static var config: Config = .default {
didSet {
logger.logLevel = config.logLevel
logger.loggers = config.loggers
}
}

private(set) var logLevel: [Log.Level] = []
private(set) var logLevel: [Log.Level] = Log.config.logLevel

private(set) var loggers: [TangemSdkLogger] = []
private(set) var loggers: [TangemSdkLogger] = Log.config.loggers

fileprivate init() {}

public static func warning<T>(_ message: @autoclosure () -> T) {
logger.logInternal(message(), level: .warning)
Expand Down Expand Up @@ -136,6 +138,8 @@ public extension Log {
case verbose
case custom(logLevel: [Log.Level],
loggers: [TangemSdkLogger] = [ConsoleLogger()])

static var `default`: Log.Config = .debug

internal var logLevel: [Log.Level] {
switch self {
Expand Down
1 change: 1 addition & 0 deletions TangemSdk/TangemSdk/Common/TLV/TlvTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ public enum TlvTag: Byte {
// MARK: - HDWallet
case walletHDPath = 0x6A
case walletHDChain = 0x6B
case walletPrivateKey = 0x6F

// MARK: - Backup
case certificate = 0x55
Expand Down
Loading

0 comments on commit d13821e

Please sign in to comment.