Skip to content

Commit

Permalink
NanoPKI tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
mbertin-ledger committed Jan 8, 2025
1 parent c34682f commit 1ad50b5
Show file tree
Hide file tree
Showing 21 changed files with 279 additions and 79 deletions.
1 change: 0 additions & 1 deletion apps/sample/src/providers/SignerEthProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ const initialState: SignerEthContextType = {
web3checksUrl: "https://api.blockaid.io/v0/ledger/transaction/scan",
mode: "prod",
branch: "main",
web3checksUrl: "https://web3-checks.api.ledger.com/v1",
},
setCalConfig: () => {},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,17 @@ export class DeviceSession {
options.triggersDisconnection,
);

return errorOrResponse.ifRight((response: ApduResponse) => {
if (CommandUtils.isLockedDeviceResponse(response)) {
this.updateDeviceStatus(DeviceStatus.LOCKED);
} else {
return errorOrResponse
.ifRight((response: ApduResponse) => {
if (CommandUtils.isLockedDeviceResponse(response)) {
this.updateDeviceStatus(DeviceStatus.LOCKED);
} else {
this.updateDeviceStatus(DeviceStatus.CONNECTED);
}
})
.ifLeft(() => {
this.updateDeviceStatus(DeviceStatus.CONNECTED);
}
});
});
}

async sendCommand<Response, Args, ErrorStatusCodes>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ export class DisconnectUseCase {
this._transportService
.getTransport(transportIdentifier)
.toEither(
new TransportNotSupportedError(new Error("Unknown transport")),
new TransportNotSupportedError(
new Error(
`Unknown transport with identifier: ${transportIdentifier}`,
),
),
),
);

Expand Down
2 changes: 2 additions & 0 deletions packages/signer/context-module/src/di.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { configModuleFactory } from "@/config/di/configModuleFactory";
import { type ContextModuleConfig } from "@/config/model/ContextModuleConfig";
import { externalPluginModuleFactory } from "@/external-plugin/di/externalPluginModuleFactory";
import { nftModuleFactory } from "@/nft/di/nftModuleFactory";
import { nanoPkiModuleFactory } from "@/pki/di/pkiModuleFactory";
import { tokenModuleFactory } from "@/token/di/tokenModuleFactory";
import { transactionModuleFactory } from "@/transaction/di/transactionModuleFactory";
import { trustedNameModuleFactory } from "@/trusted-name/di/trustedNameModuleFactory";
Expand All @@ -26,6 +27,7 @@ export const makeContainer = ({ config }: MakeContainerArgs) => {
trustedNameModuleFactory(),
typedDataModuleFactory(),
web3CheckModuleFactory(),
nanoPkiModuleFactory(),
);

return container;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ import {
PkiCertificate,
PkiCertificateInfo,
} from "@/pki/domain/pkiCertificateTypes";
import { HexStringUtils } from "@/shared/utils/HexStringUtils";
import { KeyUsageMapper } from "@/shared/utils/KeyUsageMapper";
import PACKAGE from "@root/package.json";

import { type PkiCertificateDataSource } from "./PkiCertificateDataSource";
import {
type PkiCertificateRequestDto,
type PkiCertificateResponseDto,
} from "./pkiDataSourceTypes";
import { hexaStringToBuffer } from "@ledgerhq/device-management-kit";

const KEY_USAGE = "trusted_name";
const SIGNATURE_TAG = "15";
@injectable()
export class HttpPkiCertificateDataSource implements PkiCertificateDataSource {
constructor(
Expand All @@ -26,12 +31,11 @@ export class HttpPkiCertificateDataSource implements PkiCertificateDataSource {
pkiCertificateInfo: PkiCertificateInfo,
): Promise<Either<Error, PkiCertificate | undefined>> {
const requestDto: PkiCertificateRequestDto = {
output:
"id,target_device,not_valid_after,public_key_usage,certificate_version,descriptor",
target_device: "nanox", //TODO add in input
not_valid_after: "1.3.0", //TODO add current OS_version
output: "descriptor",
target_device: pkiCertificateInfo.targetDevice,
latest: true,
descriptor: pkiCertificateInfo.descriptor,
key_id: pkiCertificateInfo.keyId,
key_usage: pkiCertificateInfo.keyUsage,
};

try {
Expand All @@ -46,7 +50,25 @@ export class HttpPkiCertificateDataSource implements PkiCertificateDataSource {
});

if (pkiCertificateResponse.status == 200) {
return Right(pkiCertificateResponse.data);
const payload = hexaStringToBuffer(
HexStringUtils.appendSignatureToPayload(
pkiCertificateResponse.data.descriptor.data,
pkiCertificateResponse.data.descriptor.signatures[
this.config.cal.mode
],
SIGNATURE_TAG,
),
);
if (!payload) {
return Left(
Error("Error encountered: Cannot convert Hex String to UInt8Array"),
);
}
const pkiCertificate: PkiCertificate = {
payload: payload,
keyUsageNumber: KeyUsageMapper.mapKeyUsageForFirmware(KEY_USAGE),
};
return Right(pkiCertificate);
} else {
return Left(
Error(
Expand Down
13 changes: 10 additions & 3 deletions packages/signer/context-module/src/pki/data/pkiDataSourceTypes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export type PkiCertificateRequestDto = {
key_id: string | undefined;
key_usage: string;
output: string;
target_device: string;
not_valid_after: string;
latest: boolean;
descriptor: string;
};

export type PkiCertificateResponseDto = {
Expand All @@ -12,5 +12,12 @@ export type PkiCertificateResponseDto = {
not_valid_after: string;
public_key_usage: string;
certificate_version: string;
descriptor: string;
descriptor: {
data: string;
descriptorType: string;
signatures: {
prod: string;
test: string;
};
};
};
12 changes: 12 additions & 0 deletions packages/signer/context-module/src/pki/di/pkiModuleFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ContainerModule } from "inversify";

import { HttpPkiCertificateDataSource } from "@/pki/data/HttpPkiCertificateDataSource";
import { DefaultPkiCertificateLoader } from "@/pki/domain/DefaultPkiCertificateLoader";

import { pkiTypes } from "./pkiDiTypes";

export const nanoPkiModuleFactory = () =>
new ContainerModule((bind, _unbind, _isBound, _rebind) => {
bind(pkiTypes.PkiCertificateDataSource).to(HttpPkiCertificateDataSource);
bind(pkiTypes.PkiCertificateLoader).to(DefaultPkiCertificateLoader);
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { PkiCertificateLoader } from "./PkiCertificateLoader";
import { PkiCertificate, PkiCertificateInfo } from "./pkiCertificateTypes";

@injectable()
export class DefaultPkiLoader implements PkiCertificateLoader {
export class DefaultPkiCertificateLoader implements PkiCertificateLoader {
private _dataSource: PkiCertificateDataSource;

constructor(
Expand All @@ -19,9 +19,10 @@ export class DefaultPkiLoader implements PkiCertificateLoader {

async loadCertificate(
certificateInfos: PkiCertificateInfo,
): Promise<PkiCertificate | null> {
await this._dataSource.fetchCertificate(certificateInfos);
): Promise<PkiCertificate | undefined> {
const certificate =
await this._dataSource.fetchCertificate(certificateInfos);

return null;
return certificate.orDefault(undefined);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import {
export interface PkiCertificateLoader {
loadCertificate(
certificateInfos: PkiCertificateInfo,
): Promise<PkiCertificate | null>;
): Promise<PkiCertificate | undefined>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum KeyUsage {
TrustedName = "trusted_name",
Web3Checks = "web3checks",
//TODO add following Docs https://ledgerhq.atlassian.net/wiki/spaces/BE/pages/4863033373/CAL+-+Raw+signing+NanoPKI+migration
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import type { KeyUsage } from "./model/KeyUsage";

export type PkiCertificate = {
id: string;
descriptor: string;
keyUsageNumber: number;
payload: Uint8Array;
};

export type PkiCertificateInfo = {
descriptor: string;
targetDevice: string;
osVersion: string;
keyUsage: KeyUsage;
keyId?: string | undefined;
};

/*
Do we re add it to PkiCertificateInfo?
osVersion: string;
*/
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PkiCertificate } from "@/pki/domain/pkiCertificateTypes";
import { type GenericPath } from "./GenericPath";

export enum ClearSignContextType {
Expand Down Expand Up @@ -71,6 +72,7 @@ export type ClearSignContextSuccess<
id: number;
payload: string;
value: number;
certificate?: PkiCertificate | undefined;
}
: {
type: Exclude<
Expand All @@ -79,7 +81,7 @@ export type ClearSignContextSuccess<
>;
payload: string;
reference?: ClearSignContextReference;
certificate?: string;
certificate?: PkiCertificate | undefined;
};

export type ClearSignContextError = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export type TransactionFieldContext =
export type TransactionContext = TransactionSubset & {
challenge: string;
domain?: string;
deviceModel?: string;
};
14 changes: 14 additions & 0 deletions packages/signer/context-module/src/shared/utils/HexStringUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,18 @@ export class HexStringUtils {
}
return hexString;
}

static appendSignatureToPayload(
payload: string,
signature: string,
tag: string,
): string {
// Ensure correct padding
if (signature.length % 2 !== 0) {
signature = "0" + signature;
}
// TLV encoding as according to trusted name documentation
const signatureLength = (signature.length / 2).toString(16);
return `${payload}${tag}${signatureLength}${signature}`;
}
}
42 changes: 42 additions & 0 deletions packages/signer/context-module/src/shared/utils/KeyUsageMapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export class KeyUsageMapper {
static mapKeyUsageForFirmware(keyUsageString: string): number {
let keyUsageNumber = -1;

switch (keyUsageString) {
case "genuine_check":
keyUsageNumber = 1;
break;
case "exchange_payload":
keyUsageNumber = 2;
break;
case "nft_meta":
keyUsageNumber = 3;
break;
case "trusted_name":
keyUsageNumber = 4;
break;
case "backup_provider":
keyUsageNumber = 5;
break;
case "protect_orchestrator":
keyUsageNumber = 6;
break;
case "plugin_meta":
keyUsageNumber = 7;
break;
case "coin_meta":
keyUsageNumber = 8;
break;
case "seed_id_auth":
keyUsageNumber = 9;
break;
case "web3checks":
keyUsageNumber = 10;
break;
default:
break;
}

return keyUsageNumber;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
ClearSignContextType,
} from "@/shared/model/ClearSignContext";
import { GenericPath } from "@/shared/model/GenericPath";
import { HexStringUtils } from "@/shared/utils/HexStringUtils";
import PACKAGE from "@root/package.json";

import {
Expand All @@ -37,6 +38,7 @@ import {
TransactionDataSource,
} from "./TransactionDataSource";

const INFO_SIGNATURE_TAG = "81ff";
@injectable()
export class HttpTransactionDataSource implements TransactionDataSource {
constructor(
Expand Down Expand Up @@ -110,7 +112,11 @@ export class HttpTransactionDataSource implements TransactionDataSource {
];
const info: ClearSignContextSuccess = {
type: ClearSignContextType.TRANSACTION_INFO,
payload: this.formatTransactionInfo(infoData, infoSignature),
payload: HexStringUtils.appendSignatureToPayload(
infoData,
infoSignature,
INFO_SIGNATURE_TAG,
),
};
const enums: ClearSignContextSuccess[] = [];
for (const [id, values] of Object.entries(calldataDescriptor.enums)) {
Expand All @@ -122,9 +128,10 @@ export class HttpTransactionDataSource implements TransactionDataSource {
type: ClearSignContextType.ENUM,
id: Number(id),
value: Number(value),
payload: this.formatTransactionInfo(
payload: HexStringUtils.appendSignatureToPayload(
data,
signatures[this.config.cal.mode]!, // the enum is validated by isCalldataDescriptorV1
signatures[this.config.cal.mode]!,
INFO_SIGNATURE_TAG,
),
});
}
Expand All @@ -147,20 +154,6 @@ export class HttpTransactionDataSource implements TransactionDataSource {
);
}

private formatTransactionInfo(
infoData: string,
infoSignature: string,
): string {
// Ensure correct padding
if (infoSignature.length % 2 !== 0) {
infoSignature = "0" + infoSignature;
}
// TLV encoding as according to generic parser documentation
const infoSignatureTag = "81ff";
const infoSignatureLength = (infoSignature.length / 2).toString(16);
return `${infoData}${infoSignatureTag}${infoSignatureLength}${infoSignature}`;
}

private getReference(
param: CalldataDescriptorParam,
): ClearSignContextReference | undefined {
Expand Down
Loading

0 comments on commit 1ad50b5

Please sign in to comment.