diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..334506a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: CI + +on: + push: + branches: + - '**' + pull_request: + +jobs: + build-test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '17' + cache: maven + + - name: Compile + run: mvn -q -DskipTests compile + + - name: Test + run: mvn -q test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5533775 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +target/ +.idea/ +.vscode/ +*.iml +.m2repo/ +.DS_Store +logs/ diff --git a/README.md b/README.md index 8e8a5c0..6d6692d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,206 @@ -# cisd.service +# TMS Framework + +Single-process TMS monolith scaffold built with: +- JDK 17 +- Spring Boot 3.5.x +- MyBatis-Plus +- TiDB (MySQL driver) +- Swagger (springdoc-openapi) + +## Quick Start + +```bash +cd tms-framework +mvn spring-boot:run +``` + +Runtime recommendation: +- Use JDK 17 for local build/test to match project and CI runtime. + +Open: +- Swagger UI: http://localhost:8080/swagger-ui.html +- Internal health API: `GET /api/v1/device/status` +- Internal sign preview API: `POST /api/v1/sign/preview` +- External sign API: `POST /openapi/v1/sign/signature` +- Init template API: `GET /api/v1/init/template` +- Init preview API: `POST /api/v1/init/preview` +- Auth login API: `POST /api/v1/auth/login` +- Device info API: `GET /api/v1/device/info` +- PCIe crypto count API: `GET /api/v1/device/crypto/device-count` +- PCIe crypto HMAC API: `POST /api/v1/device/crypto/hmac` + +## Architecture (Monolith + Modular) + +- One deployable Spring Boot application. +- Module-first packaging under `modules/*`. +- Default module layout: `controller/internal + service + repository + entity + dto`. +- `sign` module has extra `controller/openapi`, `dto/openapi`, and `support`. +- Cross-cutting concerns moved to top-level `security` and `integration`. + +## Project Structure + +```text +src/main/java/com/cisd/tms +├── TmsApplication.java +├── common +│ ├── api +│ ├── config +│ │ └── properties +│ ├── constant +│ ├── enums +│ ├── exception +│ └── util +├── infrastructure +│ └── persistence +│ ├── entity +│ ├── mapper +│ └── mybatis +├── integration +│ ├── cips +│ ├── mq +│ ├── crypto +│ └── file +├── security +│ ├── internal +│ └── openapi +└── modules + ├── system + │ ├── controller/internal + │ ├── service + │ └── dto + ├── sign + │ ├── controller/internal + │ ├── controller/openapi + │ ├── service + │ ├── dto/internal + │ ├── dto/openapi + │ ├── support + │ ├── repository + │ └── entity + ├── init + ├── auth + ├── device + ├── upgrade + ├── cert + ├── key + ├── audit + ├── backup + └── activation +``` + +```text +src/main/resources +├── application.yml +├── application-dev.yml +├── application-prod.yml +├── mapper +│ ├── init/InitTaskMapper.xml +│ ├── auth/AuthUserMapper.xml +│ └── device/DeviceNodeMapper.xml +└── db/migration + └── V1__init_auth_device_tables.sql +``` + +## API Boundary Rules + +- Internal API controllers only in `*/controller/internal`, path prefix `/api/**`. +- External API controllers only in `*/controller/openapi`, path prefix `/openapi/**`. +- Internal and external DTOs are separated. +- Cross-module calls must go through `service`, not `repository`. +- Internal token interceptor exclusions: `/api/v1/device/status`, `/api/v1/auth/login`. + +## Auth Configuration + +```yaml +tms: + security: + internal-token: ${TMS_INTERNAL_TOKEN:change-me-internal-token} + openapi: + timestamp-skew-seconds: 300 + clients: + demo-app: ${TMS_OPENAPI_DEMO_SECRET:change-me-openapi-secret} +``` + +## Crypto Card Configuration + +```yaml +tms: + crypto-card: + enabled: ${TMS_CRYPTO_CARD_ENABLED:false} + mode: ${TMS_CRYPTO_CARD_MODE:MOCK} # MOCK / JNA + vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:} + vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:swsdsdf} +``` + +- Internal PCIe debug APIs (strong-typed service): + - `GET /api/v1/device/crypto/device-count` + - `GET /api/v1/device/crypto/device-conf` + - `GET /api/v1/device/crypto/device-info` + - `GET /api/v1/device/crypto/random?length=16` + - `POST /api/v1/device/crypto/self-test` + - `POST /api/v1/device/crypto/hmac` + - `POST /api/v1/device/crypto/digest` + - `POST /api/v1/device/crypto/encrypt/plain` + - `POST /api/v1/device/crypto/decrypt/plain` + - `POST /api/v1/device/crypto/encrypt/kek` + - `POST /api/v1/device/crypto/decrypt/kek` + - `POST /api/v1/device/crypto/mac/plain` + - `POST /api/v1/device/crypto/file/create` + - `POST /api/v1/device/crypto/file/write` + - `POST /api/v1/device/crypto/file/read` + - `POST /api/v1/device/crypto/file/delete` + - `POST /api/v1/device/crypto/kek/generate` + - `GET /api/v1/device/crypto/kek/status?keyIndex=1` + - `GET /api/v1/device/crypto/lmk/seed-mac` + - `POST /api/v1/device/crypto/std/keypair/rsa` + - `POST /api/v1/device/crypto/std/keypair/ecc` + - `POST /api/v1/device/crypto/envelope/exchange/rsa` + - `POST /api/v1/device/crypto/envelope/exchange/ecc` + - `POST /api/v1/device/crypto/agreement/data-key/ecc` + - `POST /api/v1/device/crypto/agreement/session-key/ecc` + +## PCIe Crypto Unified Wrapper (JNA) + +The project keeps JNA native mappings for PCIe card `SDF/SDFE` interfaces from +`PCIE密码卡应用接口说明书 V1.02`, and provides strong-typed service APIs via +`com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService`. + +```yaml +tms: + crypto-card: + enabled: ${TMS_CRYPTO_CARD_ENABLED:false} + mode: ${TMS_CRYPTO_CARD_MODE:JNA} # MOCK / JNA + vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:} + vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:swsdsdf} +``` + +- JNA native mapping: `com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary` +- JNA implementation: `com.cisd.tms.integration.crypto.pcie.service.JnaPcieCryptoService` +- Mock fallback: `com.cisd.tms.integration.crypto.pcie.service.MockPcieCryptoService` + +### OpenAPI Signature Rules + +- Headers: `X-App-Id`, `X-Timestamp`, `X-Nonce`, `X-Signature` +- Canonical string: `appId + "\\n" + timestamp + "\\n" + nonce` +- Signature algorithm: `HMAC-SHA256` with app secret, lowercase hex +- Replay protection: nonce one-time in time window + +## Build And Test + +```bash +mvn -q -DskipTests compile +mvn -q test +``` + +- CI is pinned to JDK 17 via `.github/workflows/ci.yml`. +- Maven Surefire preloads Mockito javaagent to avoid dynamic self-attach failures on newer JDKs. + +## Current Status + +- Structure refactored to lightweight monolith modules. +- Internal and external API entry points separated. +- Basic auth interceptors for internal/openapi are in place. +- `init/auth/device/sign/system` modules have runnable skeleton controllers and services. +- `init/auth/device` modules include mapper+xml+repository-impl+DDL skeleton for TiDB. +>>>>>>> aeb6a4d (初始化项目) diff --git a/docs/plans/2026-02-28-jdk21-mockito-ci-stability-plan.md b/docs/plans/2026-02-28-jdk21-mockito-ci-stability-plan.md new file mode 100644 index 0000000..2fdf058 --- /dev/null +++ b/docs/plans/2026-02-28-jdk21-mockito-ci-stability-plan.md @@ -0,0 +1,48 @@ +# JDK17 + Mockito + CI Stability Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Stabilize local/CI test execution by fixing Mockito agent startup behavior and pinning CI to JDK 17. + +**Architecture:** Configure Maven Surefire to preload Mockito as a javaagent and set required JVM flags to avoid runtime self-attach failures. Add a CI workflow that always uses JDK 17 and runs compile/test checks. Update README for explicit developer/CI runtime expectations. + +**Tech Stack:** Maven Surefire, Mockito, GitHub Actions, JDK 17, Spring Boot 3.5 + +--- + +### Task 1: Build/Test runtime hardening + +**Files:** +- Modify: `pom.xml` + +1. Add explicit `mockito.version` property. +2. Add `maven-surefire-plugin` with `argLine` including: + - `-Djdk.attach.allowAttachSelf=true` + - `-XX:+EnableDynamicAgentLoading` + - `-javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar` + +### Task 2: CI JDK pinning + +**Files:** +- Create: `.github/workflows/ci.yml` + +1. Add workflow on `push` + `pull_request`. +2. Use `actions/setup-java` with Temurin `17`. +3. Run `mvn -q -DskipTests compile` then `mvn -q test`. + +### Task 3: Documentation sync + +**Files:** +- Modify: `README.md` + +1. Add explicit local recommended JDK 17 note. +2. Add CI note: workflow runs JDK 17 and compile+test. +3. Add troubleshooting note for Mockito agent behavior on newer JDKs. + +### Task 4: Verification + +**Commands:** +1. `mvn -q -DskipTests compile` +2. `mvn -q test` (sandbox) +3. `mvn -q test` (escalated fallback if sandbox attach restrictions block) +4. Key checks with `rg` for workflow and surefire config. diff --git a/docs/plans/2026-02-28-pcie-crypto-typed-service-design.md b/docs/plans/2026-02-28-pcie-crypto-typed-service-design.md new file mode 100644 index 0000000..0bd22a0 --- /dev/null +++ b/docs/plans/2026-02-28-pcie-crypto-typed-service-design.md @@ -0,0 +1,168 @@ +# PCIe密码卡强类型封装设计(第一期) + +- 日期:2026-02-28 +- 范围:基于 `0018接口.pdf`(国密标准SDF)与 `PCIE密码卡应用接口说明书.docx`(SDFE扩展) +- 目标:为上层提供强类型业务方法,屏蔽底层JNA细节 + +## 1. 设计目标与约束 + +### 1.1 目标 + +1. 提供强类型业务方法,不要求上层使用 `execute(command, params)`。 +2. 采用短连接会话模型:每个业务方法内部完成 `openDevice/openSession/call/closeSession/closeDevice`。 +3. 第一期开通核心子集接口,覆盖设备管理、会话、HMAC、LMK与常用密钥管理。 +4. 统一错误模型与错误码映射,便于上层处理与运维排障。 + +### 1.2 非目标 + +1. 不在第一期覆盖文档所有SDF/SDFE接口。 +2. 不在第一期做多设备负载均衡与高并发优化。 +3. 不在第一期实现JNI桥代码生成。 + +## 2. 方案选型 + +### 2.1 备选方案 + +1. 动态命令入口(`execute(command, params)`)+ 强类型外观。 +2. 纯强类型服务(推荐)。 +3. 从头文件自动生成绑定与服务代码。 + +### 2.2 选型结论 + +采用方案2:新增 `PcieCryptoService` 及其 `JnaPcieCryptoService` 实现, +强类型方法直接调用JNA映射,统一通过短连接模板管理句柄生命周期。 + +## 3. 总体架构 + +### 3.1 分层 + +1. `PcieCryptoService`:面向上层的强类型业务接口。 +2. `JnaPcieCryptoService`:服务实现,调用 `PcieNativeLibrary`。 +3. `PcieSessionTemplate`:统一短连接模板。 +4. `PcieNativeLibrary`:JNA native函数映射。 +5. `PcieErrorMapper`:错误码映射(`retCode -> 业务可读信息`)。 + +### 3.2 调用路径 + +上层业务 -> `PcieCryptoService` 强类型方法 -> `PcieSessionTemplate` -> `PcieNativeLibrary` -> 厂商 `.so` + +## 4. 第一期开通接口(核心子集) + +### 4.1 设备与会话 + +1. `getDeviceNumber()` -> `SDFE_GetDeviceNumber` +2. `getNormalDeviceNumber()` -> `SDFE_GetNormalDeviceNumber` +3. `deviceSelfTest()` -> `SDFE_DeviceSelfTest` +4. `deviceConfGet()` -> `SDFE_DeviceConfGet` +5. `initIdentify(oldPin, newPin)` -> `SDFE_InitIdentify` + +> 注:`open/close` 作为模板内部行为,不暴露给上层业务接口。 + +### 4.2 常用密钥管理(用户确认的8组) + +1. `generateKeyPairEcc` / `generateKeyPairRsa` +2. `generateKek` +3. `backupUserKey` / `recoverUserKey` +4. `backupKek` / `recoverKek` +5. `deleteUserKey` / `deleteKek` +6. `statusUserKeyEcc` / `statusUserKeyRsa` +7. `statusKek` +8. `changePrivateKeyAccessPassword` + +### 4.3 HMAC + +1. `hmac(algId, key, data)` +2. 内部流程:`SDFE_HmacInit` -> `SDFE_HmacUpdate` -> `SDFE_HmacFinal` + +### 4.4 LMK(核心) + +1. `generateLmk` / `loadLmk` / `backupLmk` / `recoverLmk` / `destroyLmk` +2. `checkLmk` / `exportLmkSeedMac` + +## 5. 强类型模型 + +### 5.1 请求对象 + +1. `GenerateKeyRequest`:`keyIndex`, `keyBits`, `keyType` +2. `RecoverUserKeyRequest`:`keyIndex`, `keyType`, `cipherKeyData`, `storeFlag` +3. `RecoverKekRequest`:`keyIndex`, `cipherKeyData` +4. `ChangePrivateKeyPasswordRequest`:`keyIndex`, `oldPassword`, `newPassword` +5. `HmacRequest`:`algId`, `key`, `data` + +### 5.2 响应对象 + +1. `OperationResult`:`success`, `retCode`, `message` +2. `DeviceCountResult`:`deviceNumber`, `normalDeviceNumber` +3. `DeviceConfResult`:映射 `SDFE_DeviceConf` +4. `BackupUserKeyResult` / `BackupKekResult`:`data`, `length` +5. `KeyStatusResult`:`keyState` +6. `HmacResult`:`hmac`, `hmacLength` + +## 6. 会话模板(短连接) + +定义统一模板方法: + +```text +executeWithSession(apiName, callback): + SDF_OpenDevice + SDF_OpenSession + callback(session) + SDF_CloseSession + SDF_CloseDevice +``` + +约束: + +1. 所有强类型方法必须通过模板执行。 +2. 关闭失败仅记录日志,不覆盖主调用错误。 +3. 模板保证异常场景也能回收句柄。 + +## 7. 错误处理 + +1. `retCode == 0`:成功。 +2. `retCode != 0`:抛 `PcieCryptoException(apiName, retCode, mappedMessage)`。 +3. 映射文档补充错误码: + - `SDR_UKEYERR` + - `SDR_GENKEYERR` + - `SDR_STATEERR` + - `SDR_RETRYERR` + - `SDR_DEVICE_BUSY` + - `SDR_RET_ERR_STATUS` + - `SDR_RET_INIT_STATUS` + - `SDR_RET_LOGINED` + - `SDR_RET_GD32_TIMEOUT` +4. 参数校验失败在服务层抛 `IllegalArgumentException`,不下发至设备。 + +## 8. 并发与安全 + +1. 第一期开启串行访问(单设备锁)避免状态错乱。 +2. PIN/口令参数不打印明文日志。 +3. 密钥备份字节在服务层保持二进制,不做文本日志输出。 + +## 9. 对上层的使用方式 + +示例: + +1. `pcieCryptoService.generateLmk()` +2. `pcieCryptoService.backupKek(keyIndex, outBufferSize)` +3. `pcieCryptoService.hmac(request)` + +上层仅依赖强类型接口与DTO,不直接依赖JNA类型和指针。 + +## 10. 验收标准 + +1. 强类型接口可完成第一期核心子集调用。 +2. 每个方法均使用短连接模板。 +3. 统一异常中包含 `apiName + retCode + mappedMessage`。 +4. `mvn -DskipTests compile` 通过。 +5. 关键路径联调用例可跑通: + - `getDeviceNumber` + - `deviceConfGet` + - `hmac` + - `generateKek + statusKek` + +## 11. 后续扩展 + +1. 第二期覆盖U盾与内部密钥管理。 +2. 第三期覆盖全量SDF/SDFE并补充结构体严格对齐校验。 +3. 加入真实设备集成测试与回放测试。 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b934f21 --- /dev/null +++ b/pom.xml @@ -0,0 +1,140 @@ + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.5.0 + + + + com.cisd + tms-framework + 0.0.1-SNAPSHOT + tms-framework + CISD TMS base framework + + + 17 + 3.5.10.1 + 2.8.5 + 5.17.0 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-aop + + + + com.baomidou + mybatis-plus-spring-boot3-starter + ${mybatis-plus.version} + + + com.mysql + mysql-connector-j + runtime + + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + net.java.dev.jna + jna + 5.14.0 + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Djdk.attach.allowAttachSelf=true -XX:+EnableDynamicAgentLoading -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + ci + + + env.CI + + + + + + org.apache.maven.plugins + maven-enforcer-plugin + + + enforce-java-17-in-ci + + enforce + + + + + [17,18) + + + + + + + + + + + diff --git a/src/main/java/com/cisd/tms/TmsApplication.java b/src/main/java/com/cisd/tms/TmsApplication.java new file mode 100644 index 0000000..239bb5b --- /dev/null +++ b/src/main/java/com/cisd/tms/TmsApplication.java @@ -0,0 +1,14 @@ +package com.cisd.tms; + +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@ConfigurationPropertiesScan +public class TmsApplication { + + public static void main(String[] args) { + SpringApplication.run(TmsApplication.class, args); + } +} diff --git a/src/main/java/com/cisd/tms/common/api/ApiResponse.java b/src/main/java/com/cisd/tms/common/api/ApiResponse.java new file mode 100644 index 0000000..21fed58 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/api/ApiResponse.java @@ -0,0 +1,128 @@ +package com.cisd.tms.common.api; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.time.Instant; +import java.util.Map; +import org.slf4j.MDC; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ApiResponse { + + private static final int SUCCESS_CODE = 200; + private static final String DEFAULT_SUCCESS_MSG = "success"; + + private boolean success; + private int code; + private String msg; + private T data; + private long timestamp; + private String traceId; + private String path; + private Map details; + + public ApiResponse() { + } + + public ApiResponse(boolean success, int code, String msg, T data) { + this.success = success; + this.code = code; + this.msg = msg; + this.data = data; + this.timestamp = Instant.now().toEpochMilli(); + this.traceId = MDC.get("traceId"); + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public String getTraceId() { + return traceId; + } + + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Map getDetails() { + return details; + } + + public void setDetails(Map details) { + this.details = details; + } + + public ApiResponse withPath(String path) { + this.path = path; + return this; + } + + public ApiResponse withDetails(Map details) { + this.details = details; + return this; + } + + public static ApiResponse success(T data) { + return new ApiResponse<>(true, SUCCESS_CODE, DEFAULT_SUCCESS_MSG, data); + } + + public static ApiResponse success(String msg, T data) { + return new ApiResponse<>(true, SUCCESS_CODE, msg, data); + } + + public static ApiResponse success() { + return new ApiResponse<>(true, SUCCESS_CODE, DEFAULT_SUCCESS_MSG, null); + } + + public static ApiResponse fail(int code, String msg) { + return new ApiResponse<>(false, code, msg, null); + } + + public static ApiResponse fail(int code, String msg, T data) { + return new ApiResponse<>(false, code, msg, data); + } +} diff --git a/src/main/java/com/cisd/tms/common/config/MybatisPlusConfig.java b/src/main/java/com/cisd/tms/common/config/MybatisPlusConfig.java new file mode 100644 index 0000000..96d9499 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/config/MybatisPlusConfig.java @@ -0,0 +1,14 @@ +package com.cisd.tms.common.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MybatisPlusConfig { + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + return new MybatisPlusInterceptor(); + } +} diff --git a/src/main/java/com/cisd/tms/common/config/OpenApiConfig.java b/src/main/java/com/cisd/tms/common/config/OpenApiConfig.java new file mode 100644 index 0000000..d6f9fb0 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/config/OpenApiConfig.java @@ -0,0 +1,42 @@ +package com.cisd.tms.common.config; + +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springdoc.core.models.GroupedOpenApi; + +@Configuration +public class OpenApiConfig { + + @Bean + public OpenAPI tmsOpenApi() { + return new OpenAPI() + .info(new Info() + .title("CISD TMS API") + .description("CISD Terminal Management System API") + .version("v0.0.1") + .license(new License().name("Internal Use"))) + .externalDocs(new ExternalDocumentation() + .description("CISD design docs") + .url("https://example.internal/cisd")); + } + + @Bean + public GroupedOpenApi internalApiGroup() { + return GroupedOpenApi.builder() + .group("internal-api") + .pathsToMatch("/api/**") + .build(); + } + + @Bean + public GroupedOpenApi openApiGroup() { + return GroupedOpenApi.builder() + .group("openapi-sign") + .pathsToMatch("/openapi/**") + .build(); + } +} diff --git a/src/main/java/com/cisd/tms/common/config/WebMvcConfig.java b/src/main/java/com/cisd/tms/common/config/WebMvcConfig.java new file mode 100644 index 0000000..aee63a7 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/config/WebMvcConfig.java @@ -0,0 +1,65 @@ +package com.cisd.tms.common.config; + +import com.cisd.tms.security.internal.InternalApiAuthInterceptor; +import com.cisd.tms.security.openapi.OpenApiSignAuthInterceptor; +import com.cisd.tms.common.util.TraceIdUtil; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import org.slf4j.MDC; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + + private final InternalApiAuthInterceptor internalApiAuthInterceptor; + private final OpenApiSignAuthInterceptor openApiSignAuthInterceptor; + + public WebMvcConfig( + InternalApiAuthInterceptor internalApiAuthInterceptor, + OpenApiSignAuthInterceptor openApiSignAuthInterceptor + ) { + this.internalApiAuthInterceptor = internalApiAuthInterceptor; + this.openApiSignAuthInterceptor = openApiSignAuthInterceptor; + } + + @Bean + public OncePerRequestFilter traceIdFilter() { + return new OncePerRequestFilter() { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws ServletException, IOException { + String traceId = request.getHeader("X-Trace-Id"); + if (traceId == null || traceId.isBlank()) { + traceId = TraceIdUtil.newTraceId(); + } + MDC.put("traceId", traceId); + response.setHeader("X-Trace-Id", traceId); + try { + filterChain.doFilter(request, response); + } finally { + MDC.remove("traceId"); + } + } + }; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(internalApiAuthInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns( + "/api/v1/device/status", + "/api/v1/auth/login" + ); + + registry.addInterceptor(openApiSignAuthInterceptor) + .addPathPatterns("/openapi/**"); + } +} diff --git a/src/main/java/com/cisd/tms/common/config/properties/TmsSecurityProperties.java b/src/main/java/com/cisd/tms/common/config/properties/TmsSecurityProperties.java new file mode 100644 index 0000000..4b8c50f --- /dev/null +++ b/src/main/java/com/cisd/tms/common/config/properties/TmsSecurityProperties.java @@ -0,0 +1,45 @@ +package com.cisd.tms.common.config.properties; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "tms.security") +public class TmsSecurityProperties { + + private String internalToken = "change-me-internal-token"; + private final Openapi openapi = new Openapi(); + + public String getInternalToken() { + return internalToken; + } + + public void setInternalToken(String internalToken) { + this.internalToken = internalToken; + } + + public Openapi getOpenapi() { + return openapi; + } + + public static class Openapi { + private long timestampSkewSeconds = 300; + private Map clients = new HashMap<>(); + + public long getTimestampSkewSeconds() { + return timestampSkewSeconds; + } + + public void setTimestampSkewSeconds(long timestampSkewSeconds) { + this.timestampSkewSeconds = timestampSkewSeconds; + } + + public Map getClients() { + return clients; + } + + public void setClients(Map clients) { + this.clients = clients; + } + } +} diff --git a/src/main/java/com/cisd/tms/common/constant/Profiles.java b/src/main/java/com/cisd/tms/common/constant/Profiles.java new file mode 100644 index 0000000..b286811 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/constant/Profiles.java @@ -0,0 +1,10 @@ +package com.cisd.tms.common.constant; + +public final class Profiles { + + public static final String DEV = "dev"; + public static final String PROD = "prod"; + + private Profiles() { + } +} diff --git a/src/main/java/com/cisd/tms/common/enums/ErrorCode.java b/src/main/java/com/cisd/tms/common/enums/ErrorCode.java new file mode 100644 index 0000000..fd1951f --- /dev/null +++ b/src/main/java/com/cisd/tms/common/enums/ErrorCode.java @@ -0,0 +1,26 @@ +package com.cisd.tms.common.enums; + +public enum ErrorCode { + BAD_REQUEST(400, "bad request"), + UNAUTHORIZED(4010, "unauthorized"), + VALIDATE_FAILED(4001, "parameter validation failed"), + BIZ_ERROR(5001, "business exception"), + CRYPTO_CARD_ERROR(5201, "crypto card adapter error"), + INTERNAL_ERROR(5000, "internal server error"); + + private final int code; + private final String message; + + ErrorCode(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/cisd/tms/common/exception/BizException.java b/src/main/java/com/cisd/tms/common/exception/BizException.java new file mode 100644 index 0000000..c9843ce --- /dev/null +++ b/src/main/java/com/cisd/tms/common/exception/BizException.java @@ -0,0 +1,15 @@ +package com.cisd.tms.common.exception; + +public class BizException extends RuntimeException { + + private final int code; + + public BizException(int code, String message) { + super(message); + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java b/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..5d6e4b7 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/exception/GlobalExceptionHandler.java @@ -0,0 +1,60 @@ +package com.cisd.tms.common.exception; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.common.enums.ErrorCode; +import com.cisd.tms.integration.crypto.pcie.PcieCryptoException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ApiResponse handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpServletRequest request) { + String msg = ex.getBindingResult().getAllErrors().stream() + .findFirst() + .map(error -> { + if (error instanceof FieldError fieldError) { + return fieldError.getField() + ": " + fieldError.getDefaultMessage(); + } + return error.getDefaultMessage(); + }) + .orElse(ErrorCode.VALIDATE_FAILED.getMessage()); + return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), msg).withPath(request.getRequestURI()); + } + + @ExceptionHandler(ConstraintViolationException.class) + public ApiResponse handleConstraintViolation(ConstraintViolationException ex, HttpServletRequest request) { + return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI()); + } + + @ExceptionHandler(BizException.class) + public ApiResponse handleBizException(BizException ex, HttpServletRequest request) { + return ApiResponse.fail(ex.getCode(), ex.getMessage()).withPath(request.getRequestURI()); + } + + @ExceptionHandler(IllegalArgumentException.class) + public ApiResponse handleIllegalArgument(IllegalArgumentException ex, HttpServletRequest request) { + return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI()); + } + + @ExceptionHandler(PcieCryptoException.class) + public ApiResponse handleCryptoCardException(PcieCryptoException ex, HttpServletRequest request) { + return ApiResponse.fail(ErrorCode.CRYPTO_CARD_ERROR.getCode(), ex.getMessage()) + .withPath(request.getRequestURI()); + } + + @ExceptionHandler(Exception.class) + public ApiResponse handleException(Exception ex, HttpServletRequest request) { + log.error("Unhandled exception", ex); + return ApiResponse.fail(ErrorCode.INTERNAL_ERROR.getCode(), ErrorCode.INTERNAL_ERROR.getMessage()) + .withPath(request.getRequestURI()); + } +} diff --git a/src/main/java/com/cisd/tms/common/util/HmacUtil.java b/src/main/java/com/cisd/tms/common/util/HmacUtil.java new file mode 100644 index 0000000..38ce923 --- /dev/null +++ b/src/main/java/com/cisd/tms/common/util/HmacUtil.java @@ -0,0 +1,30 @@ +package com.cisd.tms.common.util; + +import java.nio.charset.StandardCharsets; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public final class HmacUtil { + + private HmacUtil() { + } + + public static String hmacSha256Hex(String key, String content) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + byte[] digest = mac.doFinal(content.getBytes(StandardCharsets.UTF_8)); + return toHex(digest); + } catch (Exception ex) { + throw new IllegalStateException("Cannot calculate hmac", ex); + } + } + + private static String toHex(byte[] bytes) { + StringBuilder builder = new StringBuilder(bytes.length * 2); + for (byte b : bytes) { + builder.append(String.format("%02x", b)); + } + return builder.toString(); + } +} diff --git a/src/main/java/com/cisd/tms/common/util/HttpResponseUtil.java b/src/main/java/com/cisd/tms/common/util/HttpResponseUtil.java new file mode 100644 index 0000000..9bb24fc --- /dev/null +++ b/src/main/java/com/cisd/tms/common/util/HttpResponseUtil.java @@ -0,0 +1,20 @@ +package com.cisd.tms.common.util; + +import com.cisd.tms.common.api.ApiResponse; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +public final class HttpResponseUtil { + + private HttpResponseUtil() { + } + + public static void writeJson(HttpServletResponse response, int httpStatus, ApiResponse body, ObjectMapper objectMapper) + throws IOException { + response.setStatus(httpStatus); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString(body)); + } +} diff --git a/src/main/java/com/cisd/tms/common/util/TraceIdUtil.java b/src/main/java/com/cisd/tms/common/util/TraceIdUtil.java new file mode 100644 index 0000000..6d2c85c --- /dev/null +++ b/src/main/java/com/cisd/tms/common/util/TraceIdUtil.java @@ -0,0 +1,13 @@ +package com.cisd.tms.common.util; + +import java.util.UUID; + +public final class TraceIdUtil { + + private TraceIdUtil() { + } + + public static String newTraceId() { + return UUID.randomUUID().toString().replace("-", ""); + } +} diff --git a/src/main/java/com/cisd/tms/infrastructure/persistence/entity/BaseEntity.java b/src/main/java/com/cisd/tms/infrastructure/persistence/entity/BaseEntity.java new file mode 100644 index 0000000..83a5237 --- /dev/null +++ b/src/main/java/com/cisd/tms/infrastructure/persistence/entity/BaseEntity.java @@ -0,0 +1,43 @@ +package com.cisd.tms.infrastructure.persistence.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import java.time.LocalDateTime; + +public class BaseEntity { + + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } + + public LocalDateTime getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(LocalDateTime updateTime) { + this.updateTime = updateTime; + } +} diff --git a/src/main/java/com/cisd/tms/infrastructure/persistence/mapper/BaseMapperX.java b/src/main/java/com/cisd/tms/infrastructure/persistence/mapper/BaseMapperX.java new file mode 100644 index 0000000..89449b0 --- /dev/null +++ b/src/main/java/com/cisd/tms/infrastructure/persistence/mapper/BaseMapperX.java @@ -0,0 +1,6 @@ +package com.cisd.tms.infrastructure.persistence.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +public interface BaseMapperX extends BaseMapper { +} diff --git a/src/main/java/com/cisd/tms/infrastructure/persistence/mybatis/CommonMetaObjectHandler.java b/src/main/java/com/cisd/tms/infrastructure/persistence/mybatis/CommonMetaObjectHandler.java new file mode 100644 index 0000000..69d9f79 --- /dev/null +++ b/src/main/java/com/cisd/tms/infrastructure/persistence/mybatis/CommonMetaObjectHandler.java @@ -0,0 +1,21 @@ +package com.cisd.tms.infrastructure.persistence.mybatis; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import java.time.LocalDateTime; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +@Component +public class CommonMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); + this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); + } + + @Override + public void updateFill(MetaObject metaObject) { + this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); + } +} diff --git a/src/main/java/com/cisd/tms/integration/cips/package-info.java b/src/main/java/com/cisd/tms/integration/cips/package-info.java new file mode 100644 index 0000000..09dccef --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/cips/package-info.java @@ -0,0 +1,4 @@ +/** + * cips integration adapters. + */ +package com.cisd.tms.integration.cips; diff --git a/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java b/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java new file mode 100644 index 0000000..8ce6dcd --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/config/CryptoCardProperties.java @@ -0,0 +1,49 @@ +package com.cisd.tms.integration.crypto.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "tms.crypto-card") +public class CryptoCardProperties { + + public enum Mode { + MOCK, + JNA + } + + private boolean enabled; + private Mode mode = Mode.MOCK; + private String vendorLibPath; + private String vendorLibName = "swsdsdf"; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Mode getMode() { + return mode; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + public String getVendorLibPath() { + return vendorLibPath; + } + + public void setVendorLibPath(String vendorLibPath) { + this.vendorLibPath = vendorLibPath; + } + + public String getVendorLibName() { + return vendorLibName; + } + + public void setVendorLibName(String vendorLibName) { + this.vendorLibName = vendorLibName; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java b/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java new file mode 100644 index 0000000..0bd607a --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/config/PcieCryptoServiceConfiguration.java @@ -0,0 +1,35 @@ +package com.cisd.tms.integration.crypto.config; + +import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate; +import com.cisd.tms.integration.crypto.pcie.service.JnaPcieCryptoService; +import com.cisd.tms.integration.crypto.pcie.service.MockPcieCryptoService; +import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class PcieCryptoServiceConfiguration { + + private static final Logger log = LoggerFactory.getLogger(PcieCryptoServiceConfiguration.class); + + @Bean + public PcieCryptoService pcieCryptoService( + CryptoCardProperties properties, + PcieSessionTemplate sessionTemplate + ) { + if (!properties.isEnabled()) { + log.info("PCIe crypto service disabled, fallback to mock service"); + return new MockPcieCryptoService(); + } + + if (properties.getMode() == CryptoCardProperties.Mode.JNA) { + log.info("PCIe crypto service enabled in JNA mode"); + return new JnaPcieCryptoService(sessionTemplate); + } + + log.info("PCIe crypto service fallback to mock, current mode={}", properties.getMode()); + return new MockPcieCryptoService(); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/config/package-info.java b/src/main/java/com/cisd/tms/integration/crypto/config/package-info.java new file mode 100644 index 0000000..6fea552 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/config/package-info.java @@ -0,0 +1,4 @@ +/** + * Crypto card configuration and properties. + */ +package com.cisd.tms.integration.crypto.config; diff --git a/src/main/java/com/cisd/tms/integration/crypto/package-info.java b/src/main/java/com/cisd/tms/integration/crypto/package-info.java new file mode 100644 index 0000000..955f701 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/package-info.java @@ -0,0 +1,4 @@ +/** + * Crypto integration entry points. + */ +package com.cisd.tms.integration.crypto; diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieCryptoException.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieCryptoException.java new file mode 100644 index 0000000..599298e --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieCryptoException.java @@ -0,0 +1,27 @@ +package com.cisd.tms.integration.crypto.pcie; + +public class PcieCryptoException extends RuntimeException { + + private final String apiName; + private final int nativeRetCode; + + public PcieCryptoException(String apiName, int nativeRetCode, String message) { + super("[" + apiName + "] " + message + " (errorCode=" + nativeRetCode + ")"); + this.apiName = apiName; + this.nativeRetCode = nativeRetCode; + } + + public PcieCryptoException(String apiName, String message, Throwable cause) { + super("[" + apiName + "] " + message, cause); + this.apiName = apiName; + this.nativeRetCode = -1; + } + + public String getApiName() { + return apiName; + } + + public int getNativeRetCode() { + return nativeRetCode; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieErrorMapper.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieErrorMapper.java new file mode 100644 index 0000000..45770d1 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieErrorMapper.java @@ -0,0 +1,38 @@ +package com.cisd.tms.integration.crypto.pcie; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.stereotype.Component; + +@Component +public class PcieErrorMapper { + + private final Map lowByteErrorMap = new HashMap<>(); + + public PcieErrorMapper() { + // From PCIe custom document (SDR_BASE + 0x1F ~ 0x27) + lowByteErrorMap.put(0x1F, "ukey error"); + lowByteErrorMap.put(0x20, "generate key error"); + lowByteErrorMap.put(0x21, "state error"); + lowByteErrorMap.put(0x22, "retry exceeded"); + lowByteErrorMap.put(0x23, "device busy"); + lowByteErrorMap.put(0x24, "error status"); + lowByteErrorMap.put(0x25, "init status"); + lowByteErrorMap.put(0x26, "already logined"); + lowByteErrorMap.put(0x27, "timeout"); + } + + public String toMessage(int retCode) { + if (retCode == 0) { + return "success"; + } + + int lowByte = retCode & 0xFF; + String known = lowByteErrorMap.get(lowByte); + if (known != null) { + return known + " (retCode=0x" + Integer.toHexString(retCode) + ")"; + } + + return "native error (retCode=0x" + Integer.toHexString(retCode) + ")"; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieKeyState.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieKeyState.java new file mode 100644 index 0000000..242d26e --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieKeyState.java @@ -0,0 +1,27 @@ +package com.cisd.tms.integration.crypto.pcie; + +public enum PcieKeyState { + NO_VALID(0), + NO_RIGHT(1), + RIGHT(2), + UNKNOWN(-1); + + private final int code; + + PcieKeyState(int code) { + this.code = code; + } + + public int getCode() { + return code; + } + + public static PcieKeyState from(int code) { + for (PcieKeyState state : values()) { + if (state.code == code) { + return state; + } + } + return UNKNOWN; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieSessionTemplate.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieSessionTemplate.java new file mode 100644 index 0000000..adf0172 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieSessionTemplate.java @@ -0,0 +1,116 @@ +package com.cisd.tms.integration.crypto.pcie; + +import com.cisd.tms.integration.crypto.config.CryptoCardProperties; +import com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary; +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.PointerByReference; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class PcieSessionTemplate { + + @FunctionalInterface + public interface DeviceCallback { + T apply(PcieNativeLibrary lib, Pointer deviceHandle); + } + + @FunctionalInterface + public interface SessionCallback { + T apply(PcieNativeLibrary lib, Pointer deviceHandle, Pointer sessionHandle); + } + + private static final Logger log = LoggerFactory.getLogger(PcieSessionTemplate.class); + + private final CryptoCardProperties properties; + private final PcieErrorMapper errorMapper; + + private final Object lock = new Object(); + private volatile PcieNativeLibrary nativeLibrary; + + public PcieSessionTemplate(CryptoCardProperties properties, PcieErrorMapper errorMapper) { + this.properties = properties; + this.errorMapper = errorMapper; + } + + public T withDevice(String apiName, DeviceCallback callback) { + synchronized (lock) { + PcieNativeLibrary lib = ensureLibraryLoaded(); + + PointerByReference deviceRef = new PointerByReference(); + int openRc = lib.SDF_OpenDevice(deviceRef); + ensureSuccess(apiName + ":SDF_OpenDevice", openRc); + + Pointer device = deviceRef.getValue(); + try { + return callback.apply(lib, device); + } finally { + int closeRc = lib.SDF_CloseDevice(device); + if (closeRc != 0) { + log.warn("{} close device failed: {}", apiName, errorMapper.toMessage(closeRc)); + } + } + } + } + + public T withSession(String apiName, SessionCallback callback) { + return withDevice(apiName, (lib, deviceHandle) -> { + PointerByReference sessionRef = new PointerByReference(); + int openSessionRc = lib.SDF_OpenSession(deviceHandle, sessionRef); + ensureSuccess(apiName + ":SDF_OpenSession", openSessionRc); + + Pointer session = sessionRef.getValue(); + try { + return callback.apply(lib, deviceHandle, session); + } finally { + int closeSessionRc = lib.SDF_CloseSession(session); + if (closeSessionRc != 0) { + log.warn("{} close session failed: {}", apiName, errorMapper.toMessage(closeSessionRc)); + } + } + }); + } + + public void ensureSuccess(String apiName, int retCode) { + if (retCode != 0) { + throw new PcieCryptoException(apiName, retCode, errorMapper.toMessage(retCode)); + } + } + + private PcieNativeLibrary ensureLibraryLoaded() { + PcieNativeLibrary cached = nativeLibrary; + if (cached != null) { + return cached; + } + + synchronized (this) { + if (nativeLibrary != null) { + return nativeLibrary; + } + + Map options = new HashMap<>(); + options.put(Library.OPTION_STRING_ENCODING, "UTF-8"); + + String libPath = properties.getVendorLibPath(); + String libName = properties.getVendorLibName(); + + try { + if (libPath != null && !libPath.isBlank()) { + nativeLibrary = Native.load(libPath, PcieNativeLibrary.class, options); + log.info("Loaded PCIe native library by path: {}", libPath); + } else { + nativeLibrary = Native.load(libName, PcieNativeLibrary.class, options); + log.info("Loaded PCIe native library by name: {}", libName); + } + } catch (UnsatisfiedLinkError ex) { + throw new PcieCryptoException("Native.load", "load PCIe native library failed", ex); + } + return nativeLibrary; + } + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieUserKeyType.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieUserKeyType.java new file mode 100644 index 0000000..7c2cb1d --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/PcieUserKeyType.java @@ -0,0 +1,16 @@ +package com.cisd.tms.integration.crypto.pcie; + +public enum PcieUserKeyType { + SIGN(0), + ENC(1); + + private final int code; + + PcieUserKeyType(int code) { + this.code = code; + } + + public int getCode() { + return code; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccCipher.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccCipher.java new file mode 100644 index 0000000..749523b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccCipher.java @@ -0,0 +1,22 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"x", "y", "m", "l", "c"}) +public class EccCipher extends Structure { + + // GM/T 0018定义为C[1]变长数组;JNA侧采用固定上限承载。 + public static final int C_MAX_LEN = 1024; + + public byte[] x = new byte[EccRefPublicKey.MAX_LEN]; + public byte[] y = new byte[EccRefPublicKey.MAX_LEN]; + public byte[] m = new byte[32]; + public int l; + public byte[] c = new byte[C_MAX_LEN]; + + @Override + protected List getFieldOrder() { + return List.of("x", "y", "m", "l", "c"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccRefPrivateKey.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccRefPrivateKey.java new file mode 100644 index 0000000..3bef2ff --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccRefPrivateKey.java @@ -0,0 +1,19 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"bits", "k"}) +public class EccRefPrivateKey extends Structure { + + public static final int MAX_BITS = 512; + public static final int MAX_LEN = (MAX_BITS + 7) / 8; + + public int bits; + public byte[] k = new byte[MAX_LEN]; + + @Override + protected List getFieldOrder() { + return List.of("bits", "k"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccRefPublicKey.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccRefPublicKey.java new file mode 100644 index 0000000..39615d5 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccRefPublicKey.java @@ -0,0 +1,20 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"bits", "x", "y"}) +public class EccRefPublicKey extends Structure { + + public static final int MAX_BITS = 512; + public static final int MAX_LEN = (MAX_BITS + 7) / 8; + + public int bits; + public byte[] x = new byte[MAX_LEN]; + public byte[] y = new byte[MAX_LEN]; + + @Override + protected List getFieldOrder() { + return List.of("bits", "x", "y"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccSignature.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccSignature.java new file mode 100644 index 0000000..1990c77 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EccSignature.java @@ -0,0 +1,16 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"r", "s"}) +public class EccSignature extends Structure { + + public byte[] r = new byte[EccRefPublicKey.MAX_LEN]; + public byte[] s = new byte[EccRefPublicKey.MAX_LEN]; + + @Override + protected List getFieldOrder() { + return List.of("r", "s"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EnvelopedKeyBlob.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EnvelopedKeyBlob.java new file mode 100644 index 0000000..9b61484 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/EnvelopedKeyBlob.java @@ -0,0 +1,21 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.NativeLong; +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"version", "symmAlgId", "bits", "encryptedPriKey", "pubKey", "eccCipherBlob"}) +public class EnvelopedKeyBlob extends Structure { + + public NativeLong version = new NativeLong(); + public NativeLong symmAlgId = new NativeLong(); + public NativeLong bits = new NativeLong(); + public byte[] encryptedPriKey = new byte[64]; + public EccRefPublicKey pubKey = new EccRefPublicKey(); + public EccCipher eccCipherBlob = new EccCipher(); + + @Override + protected List getFieldOrder() { + return List.of("version", "symmAlgId", "bits", "encryptedPriKey", "pubKey", "eccCipherBlob"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/PcieNativeLibrary.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/PcieNativeLibrary.java new file mode 100644 index 0000000..a69d744 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/PcieNativeLibrary.java @@ -0,0 +1,263 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Library; +import com.sun.jna.Pointer; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; + +public interface PcieNativeLibrary extends Library { + + int SDF_OpenDevice(PointerByReference phDeviceHandle); + + int SDF_CloseDevice(Pointer hDeviceHandle); + + int SDF_OpenSession(Pointer hDeviceHandle, PointerByReference phSessionHandle); + + int SDF_CloseSession(Pointer hSessionHandle); + + int SDF_GetPrivateKeyAccessRight(Pointer hSessionHandle, int uiKeyIndex, byte[] pucPassword, int uiPwdLength); + + int SDF_ReleasePrivateKeyAccessRight(Pointer hSessionHandle, int uiKeyIndex); + + int SDF_GetDeviceInfo(Pointer hSessionHandle, SdfDeviceInfo deviceInfo); + + int SDF_GenerateRandom(Pointer hSessionHandle, int uiLength, byte[] pucRandom); + + int SDF_ImportKey(Pointer hSessionHandle, byte[] pucKey, int uiKeyLength, PointerByReference phKeyHandle); + + int SDF_ImportKeyWithKEK(Pointer hSessionHandle, int uiAlgID, byte[] pucKey, int uiKeyLength, + int uiKEKIndex, PointerByReference phKeyHandle); + + int SDF_GenerateKeyWithKEK(Pointer hSessionHandle, int uiKeyBits, int uiAlgID, int uiKEKIndex, + byte[] pucKey, IntByReference puiKeyLength, PointerByReference phKeyHandle); + + int SDF_DestroyKey(Pointer hSessionHandle, Pointer hKeyHandle); + + int SDF_ExportSignPublicKey_RSA(Pointer hSessionHandle, int uiKeyIndex, RsaRefPublicKey pucPublicKey); + + int SDF_ExportEncPublicKey_RSA(Pointer hSessionHandle, int uiKeyIndex, RsaRefPublicKey pucPublicKey); + + int SDF_ExportSignPublicKey_ECC(Pointer hSessionHandle, int uiKeyIndex, EccRefPublicKey pucPublicKey); + + int SDF_ExportEncPublicKey_ECC(Pointer hSessionHandle, int uiKeyIndex, EccRefPublicKey pucPublicKey); + + int SDF_GenerateKeyPair_RSA(Pointer hSessionHandle, int uiKeyBits, RsaRefPublicKey pucPublicKey, RsaRefPrivateKey pucPrivateKey); + + int SDF_GenerateKeyPair_ECC(Pointer hSessionHandle, int uiAlgID, int uiKeyBits, EccRefPublicKey pucPublicKey, EccRefPrivateKey pucPrivateKey); + + int SDF_ExternalPublicKeyOperation_RSA(Pointer hSessionHandle, RsaRefPublicKey pucPublicKey, + byte[] pucInput, int uiInputLength, + byte[] pucOutput, IntByReference puiOutputLength); + + int SDF_ExternalPrivateKeyOperation_RSA(Pointer hSessionHandle, RsaRefPrivateKey pucPrivateKey, + byte[] pucInput, int uiInputLength, + byte[] pucOutput, IntByReference puiOutputLength); + + int SDF_InternalPublicKeyOperation_RSA(Pointer hSessionHandle, int uiKeyIndex, + byte[] pucInput, int uiInputLength, + byte[] pucOutput, IntByReference puiOutputLength); + + int SDF_InternalPrivateKeyOperation_RSA(Pointer hSessionHandle, int uiKeyIndex, + byte[] pucInput, int uiInputLength, + byte[] pucOutput, IntByReference puiOutputLength); + + int SDF_InternalSign_ECC(Pointer hSessionHandle, int uiISKIndex, byte[] pucData, int uiDataLength, EccSignature pucSignature); + + int SDF_InternalVerify_ECC(Pointer hSessionHandle, int uiISKIndex, byte[] pucData, int uiDataLength, EccSignature pucSignature); + + int SDF_ExternalSign_ECC(Pointer hSessionHandle, int uiAlgID, EccRefPrivateKey pucPrivateKey, + byte[] pucData, int uiDataLength, EccSignature pucSignature); + + int SDF_ExternalVerify_ECC(Pointer hSessionHandle, int uiAlgID, EccRefPublicKey pucPublicKey, + byte[] pucData, int uiDataLength, EccSignature pucSignature); + + int SDF_ExternalEncrypt_ECC(Pointer hSessionHandle, int uiAlgID, EccRefPublicKey pucPublicKey, + byte[] pucData, int uiDataLength, EccCipher pucEncData); + + int SDF_ExternalDecrypt_ECC(Pointer hSessionHandle, int uiAlgID, EccRefPrivateKey pucPrivateKey, EccCipher pucEncData, + byte[] pucData, IntByReference puiDataLength); + + int SDF_GenerateKeyWithIPK_RSA(Pointer hSessionHandle, int uiIPKIndex, int uiKeyBits, + byte[] pucKey, IntByReference puiKeyLength, PointerByReference phKeyHandle); + + int SDF_GenerateKeyWithEPK_RSA(Pointer hSessionHandle, int uiKeyBits, RsaRefPublicKey pucPublicKey, + byte[] pucKey, IntByReference puiKeyLength, PointerByReference phKeyHandle); + + int SDF_ImportKeyWithISK_RSA(Pointer hSessionHandle, int uiISKIndex, byte[] pucKey, int uiKeyLength, + PointerByReference phKeyHandle); + + int SDF_GenerateKeyWithIPK_ECC(Pointer hSessionHandle, int uiIPKIndex, int uiKeyBits, + EccCipher pucKey, PointerByReference phKeyHandle); + + int SDF_GenerateKeyWithEPK_ECC(Pointer hSessionHandle, int uiKeyBits, int uiAlgID, EccRefPublicKey pucPublicKey, + EccCipher pucKey, PointerByReference phKeyHandle); + + int SDF_ImportKeyWithISK_ECC(Pointer hSessionHandle, int uiISKIndex, EccCipher pucKey, PointerByReference phKeyHandle); + + int SDF_GenerateAgreementDataAndKeyWithECC(Pointer hSessionHandle, int uiISKIndex, int uiKeyBits, + byte[] pucResponseID, int uiResponseIDLength, + byte[] pucSponsorID, int uiSponsorIDLength, + EccRefPublicKey pucSponsorPublicKey, EccRefPublicKey pucSponsorTmpPublicKey, + EccRefPublicKey pucResponsePublicKey, EccRefPublicKey pucResponseTmpPublicKey, + PointerByReference phKeyHandle); + + int SDF_GenerateAgreementDataWithECC(Pointer hSessionHandle, int uiISKIndex, int uiKeyBits, + byte[] pucSponsorID, int uiSponsorIDLength, + EccRefPublicKey pucSponsorPublicKey, EccRefPublicKey pucSponsorTmpPublicKey, + PointerByReference phAgreementHandle); + + int SDF_GenerateKeyWithECC(Pointer hSessionHandle, byte[] pucResponseID, int uiResponseIDLength, + EccRefPublicKey pucResponsePublicKey, EccRefPublicKey pucResponseTmpPublicKey, + Pointer hAgreementHandle, + PointerByReference phKeyHandle); + + int SDF_ExchangeDigitEnvelopeBaseOnRSA(Pointer hSessionHandle, int uiKeyIndex, RsaRefPublicKey pucPublicKey, + byte[] pucDEInput, int uiDELength, byte[] pucDEOutput, IntByReference puiDELength); + + int SDF_ExchangeDigitEnvelopeBaseOnECC(Pointer hSessionHandle, int uiKeyIndex, int uiAlgID, + EccRefPublicKey pucPublicKey, EccCipher pucEncDataIn, EccCipher pucEncDataOut); + + int SDF_Encrypt(Pointer hSessionHandle, Pointer hKeyHandle, int uiAlgID, byte[] pucIV, + byte[] pucData, int uiDataLength, byte[] pucEncData, IntByReference puiEncDataLength); + + int SDF_Decrypt(Pointer hSessionHandle, Pointer hKeyHandle, int uiAlgID, byte[] pucIV, + byte[] pucEncData, int uiEncDataLength, byte[] pucData, IntByReference puiDataLength); + + int SDF_CalculateMAC(Pointer hSessionHandle, Pointer hKeyHandle, int uiAlgID, byte[] pucIV, + byte[] pucData, int uiDataLength, byte[] pucMAC, IntByReference puiMACLength); + + int SDF_HashInit(Pointer hSessionHandle, int uiAlgID, EccRefPublicKey publicKey, byte[] pucID, int uiIDLength); + + int SDF_HashUpdate(Pointer hSessionHandle, byte[] pucData, int uiDataLength); + + int SDF_HashFinal(Pointer hSessionHandle, byte[] pucHash, IntByReference puiHashLength); + + int SDF_CreateFile(Pointer hSessionHandle, byte[] pucFileName, int uiNameLen, int uiFileSize); + + int SDF_DeleteFile(Pointer hSessionHandle, byte[] pucFileName, int uiNameLen); + + int SDF_ReadFile(Pointer hSessionHandle, byte[] pucFileName, int uiNameLen, int uiOffset, + IntByReference puiReadLength, byte[] pucBuffer); + + int SDF_WriteFile(Pointer hSessionHandle, byte[] pucFileName, int uiNameLen, int uiOffset, + int uiWriteLength, byte[] pucBuffer); + + int SDFE_GetDeviceNumber(IntByReference number); + + int SDFE_GetNormalDeviceNumber(Pointer hDeviceHandle, IntByReference number); + + int SDFE_ChangePrivateKeyAccessPassword(Pointer hSessionHandle, int uiKeyIndex, + byte[] oldPassword, int oldLength, + byte[] newPassword, int newLength); + + int SDFE_DeviceConfGet(Pointer hSessionHandle, SdfeDeviceConf deviceConf); + + int SDFE_InitIdentify(Pointer hSessionHandle, byte[] oldPin, int oldPinLen, byte[] newPin, int newPinLen); + + int SDFE_DeviceStatusGet(Pointer hSessionHandle, Pointer pDeviceStatus); + + int SDFE_DeviceSelfTest(Pointer hSessionHandle); + + int SDFE_DeviceFactoryReset(Pointer hSessionHandle); + + int SDFE_GenerateKeyPair_ECC(Pointer hSessionHandle, int keyBits, int keyIndex, int keyType); + + int SDFE_GenerateKeyPair_RSA(Pointer hSessionHandle, int keyBits, int keyIndex, int keyType); + + int SDFE_GenerateKEK(Pointer hSessionHandle, int keyBits, int keyIndex); + + int SDFE_ImportKeyPair_ECC(Pointer hSessionHandle, int keyIndex, int keyType, EccRefPublicKey publicKey, EccRefPrivateKey privateKey); + + int SDFE_ImportKeyPair_RSA(Pointer hSessionHandle, int keyIndex, int keyType, RsaRefPublicKey publicKey, RsaRefPrivateKey privateKey); + + int SDFE_ImportKEK(Pointer hSessionHandle, int keyIndex, byte[] keyData, int keyLen); + + int SDFE_ImportKEKComponent(Pointer hSessionHandle, int keyIndex, int componentNum, SdfeKekComponent keyComponent); + + int SDFE_ExportKEKComponent(Pointer hSessionHandle, int keyIndex, int componentNum, SdfeKekComponent keyComponent); + + int SDFE_BackupUserKey(Pointer hSessionHandle, int keyIndex, int keyType, byte[] userKey, IntByReference userKeyLen); + + int SDFE_BackupKEK(Pointer hSessionHandle, int keyIndex, byte[] key, IntByReference keyLen); + + int SDFE_RecoverUserKey(Pointer hSessionHandle, int keyIndex, int keyType, byte[] userKey, int userKeyLen, byte storeFlag); + + int SDFE_RecoverKEK(Pointer hSessionHandle, int keyIndex, byte[] key, int keyLen); + + int SDFE_BackKey(Pointer hSessionHandle, byte[] keyImage, IntByReference keyImageSize); + + int SDFE_RestoryKey(Pointer hSessionHandle, byte[] keyImage, int keyImageSize); + + int SDFE_DeleteUserKey(Pointer hSessionHandle, int keyIndex); + + int SDFE_DeleteKey_KEK(Pointer hSessionHandle, int keyIndex); + + int SDFE_StatusUserKey_ECC(Pointer hSessionHandle, int keyIndex, int keyType, IntByReference keyState); + + int SDFE_StatusUserKey_RSA(Pointer hSessionHandle, int keyIndex, int keyType, IntByReference keyState); + + int SDFE_StatusKey_KEK(Pointer hSessionHandle, int keyIndex, IntByReference keyState); + + int SDFE_ImportEncKeyPair_ECC(Pointer hSessionHandle, int keyIndex, EnvelopedKeyBlob envelopedKeyBlob); + + int SDFE_ImportEncKeyPair_RSA(Pointer hSessionHandle, int keyIndex, int symAlgId, + byte[] wrappedKey, int wrappedKeyLen, + byte[] encryptedData, int encryptedDataLen); + + int SDFE_UpdateBackedKey(Pointer hSessionHandle, byte[] oldData, int oldDataLength, + byte[] newData, IntByReference newDataLength); + + int SDFE_GenerateLMK(Pointer hSessionHandle); + + int SDFE_LoadLMK(Pointer hSessionHandle); + + int SDFE_BackupLMK(Pointer hSessionHandle); + + int SDFE_RecoverLMK(Pointer hSessionHandle); + + int SDFE_DestroyLMK(Pointer hSessionHandle); + + int SDFE_ExportLMKSeedMAC(Pointer hSessionHandle, byte[] mac); + + int SDFE_CheckLMK(Pointer hSessionHandle); + + int SDFE_BackupLMK_EX(Pointer hSessionHandle, SdfeLmkComponent lmkComponent); + + int SDFE_RecoverLMK_EX(Pointer hSessionHandle, SdfeLmkComponent lmkComponent); + + int SDFE_GenerateIK(Pointer hSessionHandle, int keyType); + + int SDFE_BackupIK(Pointer hSessionHandle, int keyType); + + int SDFE_RecoverIK(Pointer hSessionHandle, int keyType); + + int SDFE_DestroyIK(Pointer hSessionHandle, int keyType); + + int SDFE_StatusIK(Pointer hSessionHandle, int keyType, IntByReference keyState); + + int SDFE_GenerateUkey(Pointer hSessionHandle, byte adminIndex, + byte[] ukeyPin, int ukeyPinLen, + byte[] loginPin, int loginPinLen); + + int SDFE_LoginUkey(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen, byte[] loginPin, int loginPinLen); + + int SDFE_ChangeUkeyPin(Pointer hSessionHandle, int pinType, byte[] oldPin, int oldPinLen, byte[] newPin, int newPinLen); + + int SDFE_UnlockUkey(Pointer hSessionHandle, byte[] adminPin, int adminPinLen, byte[] userPin, int userPinLen); + + int SDFE_ReadLMKComponent(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen); + + int SDFE_ReadUkeyIKComponent(Pointer hSessionHandle, int keyType, byte[] ukeyPin, int ukeyPinLen); + + int SDFE_GenerateCertificate(Pointer hSessionHandle, byte[] ukeyPin, int ukeyPinLen); + + int SDFE_LoginoutAdmin(Pointer hSessionHandle, byte adminIndex); + + int SDFE_LoginStatus(Pointer hSessionHandle, SdfeLoginState loginState); + + int SDFE_HmacInit(Pointer hSessionHandle, int algId, byte[] key, int keyLen); + + int SDFE_HmacUpdate(Pointer hSessionHandle, byte[] data, int dataLength); + + int SDFE_HmacFinal(Pointer hSessionHandle, byte[] hmac, IntByReference hmacLength); +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/RsaRefPrivateKey.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/RsaRefPrivateKey.java new file mode 100644 index 0000000..9b7768d --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/RsaRefPrivateKey.java @@ -0,0 +1,26 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"bits", "m", "e", "d", "prime", "pexp", "coef"}) +public class RsaRefPrivateKey extends Structure { + + public static final int MAX_BITS = 2048; + public static final int MAX_LEN = (MAX_BITS + 7) / 8; + public static final int MAX_PBITS = (MAX_BITS + 1) / 2; + public static final int MAX_PLEN = (MAX_PBITS + 7) / 8; + + public int bits; + public byte[] m = new byte[MAX_LEN]; + public byte[] e = new byte[MAX_LEN]; + public byte[] d = new byte[MAX_LEN]; + public byte[] prime = new byte[2 * MAX_PLEN]; + public byte[] pexp = new byte[2 * MAX_PLEN]; + public byte[] coef = new byte[MAX_PLEN]; + + @Override + protected List getFieldOrder() { + return List.of("bits", "m", "e", "d", "prime", "pexp", "coef"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/RsaRefPublicKey.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/RsaRefPublicKey.java new file mode 100644 index 0000000..6bf001f --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/RsaRefPublicKey.java @@ -0,0 +1,20 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"bits", "m", "e"}) +public class RsaRefPublicKey extends Structure { + + public static final int MAX_BITS = 2048; + public static final int MAX_LEN = (MAX_BITS + 7) / 8; + + public int bits; + public byte[] m = new byte[MAX_LEN]; + public byte[] e = new byte[MAX_LEN]; + + @Override + protected List getFieldOrder() { + return List.of("bits", "m", "e"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfDeviceInfo.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfDeviceInfo.java new file mode 100644 index 0000000..b0e5f08 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfDeviceInfo.java @@ -0,0 +1,31 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; + +@Structure.FieldOrder({ + "issuerName", + "deviceName", + "deviceSerial", + "deviceVersion", + "standardVersion", + "asymAlgAbility", + "symAlgAbility", + "hashAlgAbility", + "bufferSize" +}) +public class SdfDeviceInfo extends Structure { + + public byte[] issuerName = new byte[40]; + public byte[] deviceName = new byte[16]; + public byte[] deviceSerial = new byte[16]; + public int deviceVersion; + public int standardVersion; + public int[] asymAlgAbility = new int[2]; + public int symAlgAbility; + public int hashAlgAbility; + public int bufferSize; + + public SdfDeviceInfo() { + super(ALIGN_NONE); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeDeviceConf.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeDeviceConf.java new file mode 100644 index 0000000..7a19b64 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeDeviceConf.java @@ -0,0 +1,27 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; + +@Structure.FieldOrder({ + "level", + "devCount", + "rsaKeyCount", + "sm2KeyCount", + "kekCount", + "sessKeyCount", + "fileSysCapacity" +}) +public class SdfeDeviceConf extends Structure { + + public int level; + public int devCount; + public int rsaKeyCount; + public int sm2KeyCount; + public int kekCount; + public int sessKeyCount; + public int fileSysCapacity; + + public SdfeDeviceConf() { + super(ALIGN_NONE); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeKekComponent.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeKekComponent.java new file mode 100644 index 0000000..440a9a4 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeKekComponent.java @@ -0,0 +1,19 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"keyLen", "component", "kekMac"}) +public class SdfeKekComponent extends Structure { + + public static final int KEK_MAX_LEN = 32; + + public byte keyLen; + public byte[] component = new byte[9 * KEK_MAX_LEN]; + public byte[] kekMac = new byte[8]; + + @Override + protected List getFieldOrder() { + return List.of("keyLen", "component", "kekMac"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeLmkComponent.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeLmkComponent.java new file mode 100644 index 0000000..52bdc1b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeLmkComponent.java @@ -0,0 +1,16 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; +import java.util.List; + +@Structure.FieldOrder({"lmkMac", "component"}) +public class SdfeLmkComponent extends Structure { + + public byte[] lmkMac = new byte[8]; + public byte[] component = new byte[3 * 16]; + + @Override + protected List getFieldOrder() { + return List.of("lmkMac", "component"); + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeLoginState.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeLoginState.java new file mode 100644 index 0000000..6783ff2 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/SdfeLoginState.java @@ -0,0 +1,11 @@ +package com.cisd.tms.integration.crypto.pcie.jna; + +import com.sun.jna.Structure; + +@Structure.FieldOrder({"admin1", "admin2", "admin3"}) +public class SdfeLoginState extends Structure { + + public int admin1; + public int admin2; + public int admin3; +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/package-info.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/package-info.java new file mode 100644 index 0000000..c2b8aec --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/jna/package-info.java @@ -0,0 +1,4 @@ +/** + * JNA bindings and provider implementation for PCIe crypto card native library. + */ +package com.cisd.tms.integration.crypto.pcie.jna; diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/AgreementDataAndKeyEccResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/AgreementDataAndKeyEccResult.java new file mode 100644 index 0000000..0acfb07 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/AgreementDataAndKeyEccResult.java @@ -0,0 +1,50 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class AgreementDataAndKeyEccResult { + + private byte[] responsePublicKey; + private int responsePublicKeyLength; + private byte[] responseTmpPublicKey; + private int responseTmpPublicKeyLength; + private boolean sessionKeyGenerated; + + public byte[] getResponsePublicKey() { + return responsePublicKey; + } + + public void setResponsePublicKey(byte[] responsePublicKey) { + this.responsePublicKey = responsePublicKey; + } + + public int getResponsePublicKeyLength() { + return responsePublicKeyLength; + } + + public void setResponsePublicKeyLength(int responsePublicKeyLength) { + this.responsePublicKeyLength = responsePublicKeyLength; + } + + public byte[] getResponseTmpPublicKey() { + return responseTmpPublicKey; + } + + public void setResponseTmpPublicKey(byte[] responseTmpPublicKey) { + this.responseTmpPublicKey = responseTmpPublicKey; + } + + public int getResponseTmpPublicKeyLength() { + return responseTmpPublicKeyLength; + } + + public void setResponseTmpPublicKeyLength(int responseTmpPublicKeyLength) { + this.responseTmpPublicKeyLength = responseTmpPublicKeyLength; + } + + public boolean isSessionKeyGenerated() { + return sessionKeyGenerated; + } + + public void setSessionKeyGenerated(boolean sessionKeyGenerated) { + this.sessionKeyGenerated = sessionKeyGenerated; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java new file mode 100644 index 0000000..c064e61 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/BackupDataResult.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class BackupDataResult { + + private byte[] data; + private int length; + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ChangePrivateKeyPasswordRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ChangePrivateKeyPasswordRequest.java new file mode 100644 index 0000000..6319abc --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ChangePrivateKeyPasswordRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ChangePrivateKeyPasswordRequest { + + private int keyIndex; + private byte[] oldPassword; + private byte[] newPassword; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getOldPassword() { + return oldPassword; + } + + public void setOldPassword(byte[] oldPassword) { + this.oldPassword = oldPassword; + } + + public byte[] getNewPassword() { + return newPassword; + } + + public void setNewPassword(byte[] newPassword) { + this.newPassword = newPassword; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceConfResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceConfResult.java new file mode 100644 index 0000000..4169d11 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceConfResult.java @@ -0,0 +1,68 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class DeviceConfResult { + + private int level; + private int devCount; + private int rsaKeyCount; + private int sm2KeyCount; + private int kekCount; + private int sessKeyCount; + private int fileSysCapacity; + + public int getLevel() { + return level; + } + + public void setLevel(int level) { + this.level = level; + } + + public int getDevCount() { + return devCount; + } + + public void setDevCount(int devCount) { + this.devCount = devCount; + } + + public int getRsaKeyCount() { + return rsaKeyCount; + } + + public void setRsaKeyCount(int rsaKeyCount) { + this.rsaKeyCount = rsaKeyCount; + } + + public int getSm2KeyCount() { + return sm2KeyCount; + } + + public void setSm2KeyCount(int sm2KeyCount) { + this.sm2KeyCount = sm2KeyCount; + } + + public int getKekCount() { + return kekCount; + } + + public void setKekCount(int kekCount) { + this.kekCount = kekCount; + } + + public int getSessKeyCount() { + return sessKeyCount; + } + + public void setSessKeyCount(int sessKeyCount) { + this.sessKeyCount = sessKeyCount; + } + + public int getFileSysCapacity() { + return fileSysCapacity; + } + + public void setFileSysCapacity(int fileSysCapacity) { + this.fileSysCapacity = fileSysCapacity; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceCountResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceCountResult.java new file mode 100644 index 0000000..3022f11 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceCountResult.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class DeviceCountResult { + + private int deviceNumber; + private int normalDeviceNumber; + + public int getDeviceNumber() { + return deviceNumber; + } + + public void setDeviceNumber(int deviceNumber) { + this.deviceNumber = deviceNumber; + } + + public int getNormalDeviceNumber() { + return normalDeviceNumber; + } + + public void setNormalDeviceNumber(int normalDeviceNumber) { + this.normalDeviceNumber = normalDeviceNumber; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceInfoResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceInfoResult.java new file mode 100644 index 0000000..ba7e5ae --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceInfoResult.java @@ -0,0 +1,95 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class DeviceInfoResult { + + private String issuerName; + private String deviceName; + private String deviceSerial; + private int deviceVersion; + private int standardVersion; + private int asymAlgAbility0; + private int asymAlgAbility1; + private int symAlgAbility; + private int hashAlgAbility; + private int bufferSize; + + public String getIssuerName() { + return issuerName; + } + + public void setIssuerName(String issuerName) { + this.issuerName = issuerName; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public String getDeviceSerial() { + return deviceSerial; + } + + public void setDeviceSerial(String deviceSerial) { + this.deviceSerial = deviceSerial; + } + + public int getDeviceVersion() { + return deviceVersion; + } + + public void setDeviceVersion(int deviceVersion) { + this.deviceVersion = deviceVersion; + } + + public int getStandardVersion() { + return standardVersion; + } + + public void setStandardVersion(int standardVersion) { + this.standardVersion = standardVersion; + } + + public int getAsymAlgAbility0() { + return asymAlgAbility0; + } + + public void setAsymAlgAbility0(int asymAlgAbility0) { + this.asymAlgAbility0 = asymAlgAbility0; + } + + public int getAsymAlgAbility1() { + return asymAlgAbility1; + } + + public void setAsymAlgAbility1(int asymAlgAbility1) { + this.asymAlgAbility1 = asymAlgAbility1; + } + + public int getSymAlgAbility() { + return symAlgAbility; + } + + public void setSymAlgAbility(int symAlgAbility) { + this.symAlgAbility = symAlgAbility; + } + + public int getHashAlgAbility() { + return hashAlgAbility; + } + + public void setHashAlgAbility(int hashAlgAbility) { + this.hashAlgAbility = hashAlgAbility; + } + + public int getBufferSize() { + return bufferSize; + } + + public void setBufferSize(int bufferSize) { + this.bufferSize = bufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceStatusResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceStatusResult.java new file mode 100644 index 0000000..e5a5dbe --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DeviceStatusResult.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class DeviceStatusResult { + + private byte[] statusData; + private int length; + + public byte[] getStatusData() { + return statusData; + } + + public void setStatusData(byte[] statusData) { + this.statusData = statusData; + } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DigestRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DigestRequest.java new file mode 100644 index 0000000..fe57146 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/DigestRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class DigestRequest { + + private int algId; + private byte[] data; + private int outBufferSize = 64; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccAgreementSessionKeyRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccAgreementSessionKeyRequest.java new file mode 100644 index 0000000..74b6dae --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccAgreementSessionKeyRequest.java @@ -0,0 +1,86 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccAgreementSessionKeyRequest { + + private int iskIndex; + private int keyBits; + private byte[] sponsorId; + private byte[] responseId; + private byte[] responsePublicKeyBlob; + private byte[] responseTmpPublicKeyBlob; + private int sponsorPublicKeyBufferSize; + private int sponsorTmpPublicKeyBufferSize; + private int sessionKeyBufferSize; + + public int getIskIndex() { + return iskIndex; + } + + public void setIskIndex(int iskIndex) { + this.iskIndex = iskIndex; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public byte[] getSponsorId() { + return sponsorId; + } + + public void setSponsorId(byte[] sponsorId) { + this.sponsorId = sponsorId; + } + + public byte[] getResponseId() { + return responseId; + } + + public void setResponseId(byte[] responseId) { + this.responseId = responseId; + } + + public byte[] getResponsePublicKeyBlob() { + return responsePublicKeyBlob; + } + + public void setResponsePublicKeyBlob(byte[] responsePublicKeyBlob) { + this.responsePublicKeyBlob = responsePublicKeyBlob; + } + + public byte[] getResponseTmpPublicKeyBlob() { + return responseTmpPublicKeyBlob; + } + + public void setResponseTmpPublicKeyBlob(byte[] responseTmpPublicKeyBlob) { + this.responseTmpPublicKeyBlob = responseTmpPublicKeyBlob; + } + + public int getSponsorPublicKeyBufferSize() { + return sponsorPublicKeyBufferSize; + } + + public void setSponsorPublicKeyBufferSize(int sponsorPublicKeyBufferSize) { + this.sponsorPublicKeyBufferSize = sponsorPublicKeyBufferSize; + } + + public int getSponsorTmpPublicKeyBufferSize() { + return sponsorTmpPublicKeyBufferSize; + } + + public void setSponsorTmpPublicKeyBufferSize(int sponsorTmpPublicKeyBufferSize) { + this.sponsorTmpPublicKeyBufferSize = sponsorTmpPublicKeyBufferSize; + } + + public int getSessionKeyBufferSize() { + return sessionKeyBufferSize; + } + + public void setSessionKeyBufferSize(int sessionKeyBufferSize) { + this.sessionKeyBufferSize = sessionKeyBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccAgreementSessionKeyResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccAgreementSessionKeyResult.java new file mode 100644 index 0000000..120cd4f --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccAgreementSessionKeyResult.java @@ -0,0 +1,68 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccAgreementSessionKeyResult { + + private byte[] sponsorPublicKey; + private int sponsorPublicKeyLength; + private byte[] sponsorTmpPublicKey; + private int sponsorTmpPublicKeyLength; + private byte[] sessionKey; + private int sessionKeyLength; + private boolean sessionKeyGenerated; + + public byte[] getSponsorPublicKey() { + return sponsorPublicKey; + } + + public void setSponsorPublicKey(byte[] sponsorPublicKey) { + this.sponsorPublicKey = sponsorPublicKey; + } + + public int getSponsorPublicKeyLength() { + return sponsorPublicKeyLength; + } + + public void setSponsorPublicKeyLength(int sponsorPublicKeyLength) { + this.sponsorPublicKeyLength = sponsorPublicKeyLength; + } + + public byte[] getSponsorTmpPublicKey() { + return sponsorTmpPublicKey; + } + + public void setSponsorTmpPublicKey(byte[] sponsorTmpPublicKey) { + this.sponsorTmpPublicKey = sponsorTmpPublicKey; + } + + public int getSponsorTmpPublicKeyLength() { + return sponsorTmpPublicKeyLength; + } + + public void setSponsorTmpPublicKeyLength(int sponsorTmpPublicKeyLength) { + this.sponsorTmpPublicKeyLength = sponsorTmpPublicKeyLength; + } + + public byte[] getSessionKey() { + return sessionKey; + } + + public void setSessionKey(byte[] sessionKey) { + this.sessionKey = sessionKey; + } + + public int getSessionKeyLength() { + return sessionKeyLength; + } + + public void setSessionKeyLength(int sessionKeyLength) { + this.sessionKeyLength = sessionKeyLength; + } + + public boolean isSessionKeyGenerated() { + return sessionKeyGenerated; + } + + public void setSessionKeyGenerated(boolean sessionKeyGenerated) { + this.sessionKeyGenerated = sessionKeyGenerated; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalDecryptRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalDecryptRequest.java new file mode 100644 index 0000000..9a1569c --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalDecryptRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccExternalDecryptRequest { + + private int algId; + private byte[] privateKeyBlob; + private byte[] encryptedData; + private int outBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getPrivateKeyBlob() { + return privateKeyBlob; + } + + public void setPrivateKeyBlob(byte[] privateKeyBlob) { + this.privateKeyBlob = privateKeyBlob; + } + + public byte[] getEncryptedData() { + return encryptedData; + } + + public void setEncryptedData(byte[] encryptedData) { + this.encryptedData = encryptedData; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalEncryptRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalEncryptRequest.java new file mode 100644 index 0000000..004b291 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalEncryptRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccExternalEncryptRequest { + + private int algId; + private byte[] publicKeyBlob; + private byte[] data; + private int outBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalSignRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalSignRequest.java new file mode 100644 index 0000000..a3d7feb --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalSignRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccExternalSignRequest { + + private int algId; + private byte[] privateKeyBlob; + private byte[] data; + private int signatureBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getPrivateKeyBlob() { + return privateKeyBlob; + } + + public void setPrivateKeyBlob(byte[] privateKeyBlob) { + this.privateKeyBlob = privateKeyBlob; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getSignatureBufferSize() { + return signatureBufferSize; + } + + public void setSignatureBufferSize(int signatureBufferSize) { + this.signatureBufferSize = signatureBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalVerifyRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalVerifyRequest.java new file mode 100644 index 0000000..b94dea8 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccExternalVerifyRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccExternalVerifyRequest { + + private int algId; + private byte[] publicKeyBlob; + private byte[] data; + private byte[] signature; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public byte[] getSignature() { + return signature; + } + + public void setSignature(byte[] signature) { + this.signature = signature; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccInternalSignRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccInternalSignRequest.java new file mode 100644 index 0000000..b59f617 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccInternalSignRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccInternalSignRequest { + + private int keyIndex; + private byte[] data; + private int signatureBufferSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getSignatureBufferSize() { + return signatureBufferSize; + } + + public void setSignatureBufferSize(int signatureBufferSize) { + this.signatureBufferSize = signatureBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccInternalVerifyRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccInternalVerifyRequest.java new file mode 100644 index 0000000..df56170 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/EccInternalVerifyRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class EccInternalVerifyRequest { + + private int keyIndex; + private byte[] data; + private byte[] signature; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public byte[] getSignature() { + return signature; + } + + public void setSignature(byte[] signature) { + this.signature = signature; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExchangeDigitEnvelopeEccRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExchangeDigitEnvelopeEccRequest.java new file mode 100644 index 0000000..ddc744b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExchangeDigitEnvelopeEccRequest.java @@ -0,0 +1,50 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ExchangeDigitEnvelopeEccRequest { + + private int keyIndex; + private int algId; + private byte[] publicKeyBlob; + private byte[] inputEnvelopeBlob; + private int outBufferSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public byte[] getInputEnvelopeBlob() { + return inputEnvelopeBlob; + } + + public void setInputEnvelopeBlob(byte[] inputEnvelopeBlob) { + this.inputEnvelopeBlob = inputEnvelopeBlob; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExchangeDigitEnvelopeRsaRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExchangeDigitEnvelopeRsaRequest.java new file mode 100644 index 0000000..4d9361b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExchangeDigitEnvelopeRsaRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ExchangeDigitEnvelopeRsaRequest { + + private int keyIndex; + private byte[] publicKeyBlob; + private byte[] inputEnvelopeBlob; + private int outBufferSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public byte[] getInputEnvelopeBlob() { + return inputEnvelopeBlob; + } + + public void setInputEnvelopeBlob(byte[] inputEnvelopeBlob) { + this.inputEnvelopeBlob = inputEnvelopeBlob; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExportKekComponentRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExportKekComponentRequest.java new file mode 100644 index 0000000..bec135e --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ExportKekComponentRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ExportKekComponentRequest { + + private int keyIndex; + private int componentNum; + private int componentSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getComponentNum() { + return componentNum; + } + + public void setComponentNum(int componentNum) { + this.componentNum = componentNum; + } + + public int getComponentSize() { + return componentSize; + } + + public void setComponentSize(int componentSize) { + this.componentSize = componentSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileCreateRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileCreateRequest.java new file mode 100644 index 0000000..c37e0d7 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileCreateRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class FileCreateRequest { + + private String fileName; + private int fileSize; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getFileSize() { + return fileSize; + } + + public void setFileSize(int fileSize) { + this.fileSize = fileSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileReadRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileReadRequest.java new file mode 100644 index 0000000..cda6251 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileReadRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class FileReadRequest { + + private String fileName; + private int offset; + private int readLength; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public int getReadLength() { + return readLength; + } + + public void setReadLength(int readLength) { + this.readLength = readLength; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileWriteRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileWriteRequest.java new file mode 100644 index 0000000..bb48010 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/FileWriteRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class FileWriteRequest { + + private String fileName; + private int offset; + private byte[] data; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateAgreementDataAndKeyEccRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateAgreementDataAndKeyEccRequest.java new file mode 100644 index 0000000..8915110 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateAgreementDataAndKeyEccRequest.java @@ -0,0 +1,77 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateAgreementDataAndKeyEccRequest { + + private int iskIndex; + private int keyBits; + private byte[] responseId; + private byte[] sponsorId; + private byte[] sponsorPublicKeyBlob; + private byte[] sponsorTmpPublicKeyBlob; + private int responsePublicKeyBufferSize; + private int responseTmpPublicKeyBufferSize; + + public int getIskIndex() { + return iskIndex; + } + + public void setIskIndex(int iskIndex) { + this.iskIndex = iskIndex; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public byte[] getResponseId() { + return responseId; + } + + public void setResponseId(byte[] responseId) { + this.responseId = responseId; + } + + public byte[] getSponsorId() { + return sponsorId; + } + + public void setSponsorId(byte[] sponsorId) { + this.sponsorId = sponsorId; + } + + public byte[] getSponsorPublicKeyBlob() { + return sponsorPublicKeyBlob; + } + + public void setSponsorPublicKeyBlob(byte[] sponsorPublicKeyBlob) { + this.sponsorPublicKeyBlob = sponsorPublicKeyBlob; + } + + public byte[] getSponsorTmpPublicKeyBlob() { + return sponsorTmpPublicKeyBlob; + } + + public void setSponsorTmpPublicKeyBlob(byte[] sponsorTmpPublicKeyBlob) { + this.sponsorTmpPublicKeyBlob = sponsorTmpPublicKeyBlob; + } + + public int getResponsePublicKeyBufferSize() { + return responsePublicKeyBufferSize; + } + + public void setResponsePublicKeyBufferSize(int responsePublicKeyBufferSize) { + this.responsePublicKeyBufferSize = responsePublicKeyBufferSize; + } + + public int getResponseTmpPublicKeyBufferSize() { + return responseTmpPublicKeyBufferSize; + } + + public void setResponseTmpPublicKeyBufferSize(int responseTmpPublicKeyBufferSize) { + this.responseTmpPublicKeyBufferSize = responseTmpPublicKeyBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKekRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKekRequest.java new file mode 100644 index 0000000..13f1229 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKekRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKekRequest { + + private int keyBits; + private int keyIndex; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyPairRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyPairRequest.java new file mode 100644 index 0000000..9bddab0 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyPairRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKeyPairRequest { + + private int keyBits; + private int keyIndex; + private int keyType; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getKeyType() { + return keyType; + } + + public void setKeyType(int keyType) { + this.keyType = keyType; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithEpkEccRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithEpkEccRequest.java new file mode 100644 index 0000000..77bded0 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithEpkEccRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKeyWithEpkEccRequest { + + private int keyBits; + private int algId; + private byte[] publicKeyBlob; + private int outBufferSize; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithEpkRsaRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithEpkRsaRequest.java new file mode 100644 index 0000000..2c6894c --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithEpkRsaRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKeyWithEpkRsaRequest { + + private int keyBits; + private byte[] publicKeyBlob; + private int outBufferSize; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithIpkEccRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithIpkEccRequest.java new file mode 100644 index 0000000..5742ced --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithIpkEccRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKeyWithIpkEccRequest { + + private int ipkIndex; + private int keyBits; + private int outBufferSize; + + public int getIpkIndex() { + return ipkIndex; + } + + public void setIpkIndex(int ipkIndex) { + this.ipkIndex = ipkIndex; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithIpkRsaRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithIpkRsaRequest.java new file mode 100644 index 0000000..458e75e --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithIpkRsaRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKeyWithIpkRsaRequest { + + private int ipkIndex; + private int keyBits; + private int outBufferSize; + + public int getIpkIndex() { + return ipkIndex; + } + + public void setIpkIndex(int ipkIndex) { + this.ipkIndex = ipkIndex; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithKekRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithKekRequest.java new file mode 100644 index 0000000..e000e9d --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateKeyWithKekRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateKeyWithKekRequest { + + private int keyBits; + private int algId; + private int kekIndex; + private int outBufferSize; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public int getKekIndex() { + return kekIndex; + } + + public void setKekIndex(int kekIndex) { + this.kekIndex = kekIndex; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateStandardEccKeyPairRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateStandardEccKeyPairRequest.java new file mode 100644 index 0000000..385fc8a --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateStandardEccKeyPairRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateStandardEccKeyPairRequest { + + private int algId; + private int keyBits; + private int publicKeyBufferSize; + private int privateKeyBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getPublicKeyBufferSize() { + return publicKeyBufferSize; + } + + public void setPublicKeyBufferSize(int publicKeyBufferSize) { + this.publicKeyBufferSize = publicKeyBufferSize; + } + + public int getPrivateKeyBufferSize() { + return privateKeyBufferSize; + } + + public void setPrivateKeyBufferSize(int privateKeyBufferSize) { + this.privateKeyBufferSize = privateKeyBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateStandardRsaKeyPairRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateStandardRsaKeyPairRequest.java new file mode 100644 index 0000000..51bbfe9 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/GenerateStandardRsaKeyPairRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class GenerateStandardRsaKeyPairRequest { + + private int keyBits; + private int publicKeyBufferSize; + private int privateKeyBufferSize; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getPublicKeyBufferSize() { + return publicKeyBufferSize; + } + + public void setPublicKeyBufferSize(int publicKeyBufferSize) { + this.publicKeyBufferSize = publicKeyBufferSize; + } + + public int getPrivateKeyBufferSize() { + return privateKeyBufferSize; + } + + public void setPrivateKeyBufferSize(int privateKeyBufferSize) { + this.privateKeyBufferSize = privateKeyBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/HmacRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/HmacRequest.java new file mode 100644 index 0000000..55647a1 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/HmacRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class HmacRequest { + + private int algId; + private byte[] key; + private byte[] data; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getKey() { + return key; + } + + public void setKey(byte[] key) { + this.key = key; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/HmacResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/HmacResult.java new file mode 100644 index 0000000..4849042 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/HmacResult.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class HmacResult { + + private byte[] hmac; + private int hmacLength; + + public byte[] getHmac() { + return hmac; + } + + public void setHmac(byte[] hmac) { + this.hmac = hmac; + } + + public int getHmacLength() { + return hmacLength; + } + + public void setHmacLength(int hmacLength) { + this.hmacLength = hmacLength; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportEncKeyPairEccRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportEncKeyPairEccRequest.java new file mode 100644 index 0000000..83fcb18 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportEncKeyPairEccRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ImportEncKeyPairEccRequest { + + private int keyIndex; + private byte[] envelopedKeyBlob; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getEnvelopedKeyBlob() { + return envelopedKeyBlob; + } + + public void setEnvelopedKeyBlob(byte[] envelopedKeyBlob) { + this.envelopedKeyBlob = envelopedKeyBlob; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportEncKeyPairRsaRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportEncKeyPairRsaRequest.java new file mode 100644 index 0000000..979952b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportEncKeyPairRsaRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ImportEncKeyPairRsaRequest { + + private int keyIndex; + private int symAlgId; + private byte[] wrappedKey; + private byte[] encryptedData; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getSymAlgId() { + return symAlgId; + } + + public void setSymAlgId(int symAlgId) { + this.symAlgId = symAlgId; + } + + public byte[] getWrappedKey() { + return wrappedKey; + } + + public void setWrappedKey(byte[] wrappedKey) { + this.wrappedKey = wrappedKey; + } + + public byte[] getEncryptedData() { + return encryptedData; + } + + public void setEncryptedData(byte[] encryptedData) { + this.encryptedData = encryptedData; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKekRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKekRequest.java new file mode 100644 index 0000000..028819b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKekRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ImportKekRequest { + + private int keyIndex; + private byte[] keyData; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getKeyData() { + return keyData; + } + + public void setKeyData(byte[] keyData) { + this.keyData = keyData; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyPairRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyPairRequest.java new file mode 100644 index 0000000..151ab7b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyPairRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ImportKeyPairRequest { + + private int keyIndex; + private int keyType; + private byte[] publicKey; + private byte[] privateKey; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getKeyType() { + return keyType; + } + + public void setKeyType(int keyType) { + this.keyType = keyType; + } + + public byte[] getPublicKey() { + return publicKey; + } + + public void setPublicKey(byte[] publicKey) { + this.publicKey = publicKey; + } + + public byte[] getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(byte[] privateKey) { + this.privateKey = privateKey; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyWithIskEccRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyWithIskEccRequest.java new file mode 100644 index 0000000..82915c6 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyWithIskEccRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ImportKeyWithIskEccRequest { + + private int iskIndex; + private byte[] encryptedKeyBlob; + + public int getIskIndex() { + return iskIndex; + } + + public void setIskIndex(int iskIndex) { + this.iskIndex = iskIndex; + } + + public byte[] getEncryptedKeyBlob() { + return encryptedKeyBlob; + } + + public void setEncryptedKeyBlob(byte[] encryptedKeyBlob) { + this.encryptedKeyBlob = encryptedKeyBlob; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyWithIskRsaRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyWithIskRsaRequest.java new file mode 100644 index 0000000..967393f --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/ImportKeyWithIskRsaRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class ImportKeyWithIskRsaRequest { + + private int iskIndex; + private byte[] wrappedKey; + + public int getIskIndex() { + return iskIndex; + } + + public void setIskIndex(int iskIndex) { + this.iskIndex = iskIndex; + } + + public byte[] getWrappedKey() { + return wrappedKey; + } + + public void setWrappedKey(byte[] wrappedKey) { + this.wrappedKey = wrappedKey; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/KekComponentRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/KekComponentRequest.java new file mode 100644 index 0000000..a1bf110 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/KekComponentRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class KekComponentRequest { + + private int keyIndex; + private int componentNum; + private byte[] componentData; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getComponentNum() { + return componentNum; + } + + public void setComponentNum(int componentNum) { + this.componentNum = componentNum; + } + + public byte[] getComponentData() { + return componentData; + } + + public void setComponentData(byte[] componentData) { + this.componentData = componentData; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/KeyStatusResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/KeyStatusResult.java new file mode 100644 index 0000000..eabe52c --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/KeyStatusResult.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class KeyStatusResult { + + private int keyState; + private String keyStateName; + + public int getKeyState() { + return keyState; + } + + public void setKeyState(int keyState) { + this.keyState = keyState; + } + + public String getKeyStateName() { + return keyStateName; + } + + public void setKeyStateName(String keyStateName) { + this.keyStateName = keyStateName; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/LoginStatusResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/LoginStatusResult.java new file mode 100644 index 0000000..5ef6ba8 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/LoginStatusResult.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class LoginStatusResult { + + private int admin1; + private int admin2; + private int admin3; + + public int getAdmin1() { + return admin1; + } + + public void setAdmin1(int admin1) { + this.admin1 = admin1; + } + + public int getAdmin2() { + return admin2; + } + + public void setAdmin2(int admin2) { + this.admin2 = admin2; + } + + public int getAdmin3() { + return admin3; + } + + public void setAdmin3(int admin3) { + this.admin3 = admin3; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/MacCalcRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/MacCalcRequest.java new file mode 100644 index 0000000..7f208c8 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/MacCalcRequest.java @@ -0,0 +1,50 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class MacCalcRequest { + + private int algId; + private byte[] key; + private byte[] iv; + private byte[] data; + private int outBufferSize = 32; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getKey() { + return key; + } + + public void setKey(byte[] key) { + this.key = key; + } + + public byte[] getIv() { + return iv; + } + + public void setIv(byte[] iv) { + this.iv = iv; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/PrivateKeyAccessRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/PrivateKeyAccessRequest.java new file mode 100644 index 0000000..2e65989 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/PrivateKeyAccessRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class PrivateKeyAccessRequest { + + private int keyIndex; + private byte[] password; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getPassword() { + return password; + } + + public void setPassword(byte[] password) { + this.password = password; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RecoverKekRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RecoverKekRequest.java new file mode 100644 index 0000000..770f42e --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RecoverKekRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class RecoverKekRequest { + + private int keyIndex; + private byte[] encryptedKey; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getEncryptedKey() { + return encryptedKey; + } + + public void setEncryptedKey(byte[] encryptedKey) { + this.encryptedKey = encryptedKey; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RecoverUserKeyRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RecoverUserKeyRequest.java new file mode 100644 index 0000000..38d5541 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RecoverUserKeyRequest.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class RecoverUserKeyRequest { + + private int keyIndex; + private int keyType; + private byte[] encryptedKey; + private int storeFlag = 1; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getKeyType() { + return keyType; + } + + public void setKeyType(int keyType) { + this.keyType = keyType; + } + + public byte[] getEncryptedKey() { + return encryptedKey; + } + + public void setEncryptedKey(byte[] encryptedKey) { + this.encryptedKey = encryptedKey; + } + + public int getStoreFlag() { + return storeFlag; + } + + public void setStoreFlag(int storeFlag) { + this.storeFlag = storeFlag; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaExternalPrivateKeyOpRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaExternalPrivateKeyOpRequest.java new file mode 100644 index 0000000..5873a9c --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaExternalPrivateKeyOpRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class RsaExternalPrivateKeyOpRequest { + + private byte[] privateKeyBlob; + private byte[] input; + private int outBufferSize; + + public byte[] getPrivateKeyBlob() { + return privateKeyBlob; + } + + public void setPrivateKeyBlob(byte[] privateKeyBlob) { + this.privateKeyBlob = privateKeyBlob; + } + + public byte[] getInput() { + return input; + } + + public void setInput(byte[] input) { + this.input = input; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaExternalPublicKeyOpRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaExternalPublicKeyOpRequest.java new file mode 100644 index 0000000..52601be --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaExternalPublicKeyOpRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class RsaExternalPublicKeyOpRequest { + + private byte[] publicKeyBlob; + private byte[] input; + private int outBufferSize; + + public byte[] getPublicKeyBlob() { + return publicKeyBlob; + } + + public void setPublicKeyBlob(byte[] publicKeyBlob) { + this.publicKeyBlob = publicKeyBlob; + } + + public byte[] getInput() { + return input; + } + + public void setInput(byte[] input) { + this.input = input; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaInternalKeyOpRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaInternalKeyOpRequest.java new file mode 100644 index 0000000..f80dfa2 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/RsaInternalKeyOpRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class RsaInternalKeyOpRequest { + + private int keyIndex; + private byte[] input; + private int outBufferSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public byte[] getInput() { + return input; + } + + public void setInput(byte[] input) { + this.input = input; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/StandardKeyPairResult.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/StandardKeyPairResult.java new file mode 100644 index 0000000..b0da95d --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/StandardKeyPairResult.java @@ -0,0 +1,41 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class StandardKeyPairResult { + + private byte[] publicKey; + private int publicKeyLength; + private byte[] privateKey; + private int privateKeyLength; + + public byte[] getPublicKey() { + return publicKey; + } + + public void setPublicKey(byte[] publicKey) { + this.publicKey = publicKey; + } + + public int getPublicKeyLength() { + return publicKeyLength; + } + + public void setPublicKeyLength(int publicKeyLength) { + this.publicKeyLength = publicKeyLength; + } + + public byte[] getPrivateKey() { + return privateKey; + } + + public void setPrivateKey(byte[] privateKey) { + this.privateKey = privateKey; + } + + public int getPrivateKeyLength() { + return privateKeyLength; + } + + public void setPrivateKeyLength(int privateKeyLength) { + this.privateKeyLength = privateKeyLength; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/SymmetricCryptoRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/SymmetricCryptoRequest.java new file mode 100644 index 0000000..ba9afce --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/SymmetricCryptoRequest.java @@ -0,0 +1,50 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class SymmetricCryptoRequest { + + private int algId; + private byte[] key; + private byte[] iv; + private byte[] data; + private int outBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public byte[] getKey() { + return key; + } + + public void setKey(byte[] key) { + this.key = key; + } + + public byte[] getIv() { + return iv; + } + + public void setIv(byte[] iv) { + this.iv = iv; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/SymmetricKekCryptoRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/SymmetricKekCryptoRequest.java new file mode 100644 index 0000000..7fe20b5 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/SymmetricKekCryptoRequest.java @@ -0,0 +1,59 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class SymmetricKekCryptoRequest { + + private int algId; + private int kekIndex; + private byte[] wrappedKey; + private byte[] iv; + private byte[] data; + private int outBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public int getKekIndex() { + return kekIndex; + } + + public void setKekIndex(int kekIndex) { + this.kekIndex = kekIndex; + } + + public byte[] getWrappedKey() { + return wrappedKey; + } + + public void setWrappedKey(byte[] wrappedKey) { + this.wrappedKey = wrappedKey; + } + + public byte[] getIv() { + return iv; + } + + public void setIv(byte[] iv) { + this.iv = iv; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyGenerateRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyGenerateRequest.java new file mode 100644 index 0000000..312e7ad --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyGenerateRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class UkeyGenerateRequest { + + private int adminIndex; + private byte[] ukeyPin; + private byte[] loginPin; + + public int getAdminIndex() { + return adminIndex; + } + + public void setAdminIndex(int adminIndex) { + this.adminIndex = adminIndex; + } + + public byte[] getUkeyPin() { + return ukeyPin; + } + + public void setUkeyPin(byte[] ukeyPin) { + this.ukeyPin = ukeyPin; + } + + public byte[] getLoginPin() { + return loginPin; + } + + public void setLoginPin(byte[] loginPin) { + this.loginPin = loginPin; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyLoginRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyLoginRequest.java new file mode 100644 index 0000000..d1602b0 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyLoginRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class UkeyLoginRequest { + + private byte[] ukeyPin; + private byte[] loginPin; + + public byte[] getUkeyPin() { + return ukeyPin; + } + + public void setUkeyPin(byte[] ukeyPin) { + this.ukeyPin = ukeyPin; + } + + public byte[] getLoginPin() { + return loginPin; + } + + public void setLoginPin(byte[] loginPin) { + this.loginPin = loginPin; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyPinChangeRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyPinChangeRequest.java new file mode 100644 index 0000000..aca2685 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyPinChangeRequest.java @@ -0,0 +1,32 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class UkeyPinChangeRequest { + + private int pinType; + private byte[] oldPin; + private byte[] newPin; + + public int getPinType() { + return pinType; + } + + public void setPinType(int pinType) { + this.pinType = pinType; + } + + public byte[] getOldPin() { + return oldPin; + } + + public void setOldPin(byte[] oldPin) { + this.oldPin = oldPin; + } + + public byte[] getNewPin() { + return newPin; + } + + public void setNewPin(byte[] newPin) { + this.newPin = newPin; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyUnlockRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyUnlockRequest.java new file mode 100644 index 0000000..eacd963 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UkeyUnlockRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class UkeyUnlockRequest { + + private byte[] adminPin; + private byte[] userPin; + + public byte[] getAdminPin() { + return adminPin; + } + + public void setAdminPin(byte[] adminPin) { + this.adminPin = adminPin; + } + + public byte[] getUserPin() { + return userPin; + } + + public void setUserPin(byte[] userPin) { + this.userPin = userPin; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UpdateBackedKeyRequest.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UpdateBackedKeyRequest.java new file mode 100644 index 0000000..b386c4b --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/model/UpdateBackedKeyRequest.java @@ -0,0 +1,23 @@ +package com.cisd.tms.integration.crypto.pcie.model; + +public class UpdateBackedKeyRequest { + + private byte[] oldData; + private int newDataBufferSize; + + public byte[] getOldData() { + return oldData; + } + + public void setOldData(byte[] oldData) { + this.oldData = oldData; + } + + public int getNewDataBufferSize() { + return newDataBufferSize; + } + + public void setNewDataBufferSize(int newDataBufferSize) { + this.newDataBufferSize = newDataBufferSize; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/package-info.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/package-info.java new file mode 100644 index 0000000..f550c2d --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/package-info.java @@ -0,0 +1,4 @@ +/** + * Unified PCIe crypto card wrapper for SDF/SDFE commands. + */ +package com.cisd.tms.integration.crypto.pcie; diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java new file mode 100644 index 0000000..f51aef4 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/JnaPcieCryptoService.java @@ -0,0 +1,2037 @@ +package com.cisd.tms.integration.crypto.pcie.service; + +import com.cisd.tms.integration.crypto.pcie.PcieCryptoException; +import com.cisd.tms.integration.crypto.pcie.PcieKeyState; +import com.cisd.tms.integration.crypto.pcie.PcieSessionTemplate; +import com.cisd.tms.integration.crypto.pcie.PcieUserKeyType; +import com.cisd.tms.integration.crypto.pcie.jna.EccCipher; +import com.cisd.tms.integration.crypto.pcie.jna.EccRefPrivateKey; +import com.cisd.tms.integration.crypto.pcie.jna.EccRefPublicKey; +import com.cisd.tms.integration.crypto.pcie.jna.EccSignature; +import com.cisd.tms.integration.crypto.pcie.jna.EnvelopedKeyBlob; +import com.cisd.tms.integration.crypto.pcie.jna.PcieNativeLibrary; +import com.cisd.tms.integration.crypto.pcie.jna.RsaRefPrivateKey; +import com.cisd.tms.integration.crypto.pcie.jna.RsaRefPublicKey; +import com.cisd.tms.integration.crypto.pcie.jna.SdfDeviceInfo; +import com.cisd.tms.integration.crypto.pcie.jna.SdfeDeviceConf; +import com.cisd.tms.integration.crypto.pcie.jna.SdfeKekComponent; +import com.cisd.tms.integration.crypto.pcie.jna.SdfeLmkComponent; +import com.cisd.tms.integration.crypto.pcie.jna.SdfeLoginState; +import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult; +import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult; +import com.cisd.tms.integration.crypto.pcie.model.ChangePrivateKeyPasswordRequest; +import com.cisd.tms.integration.crypto.pcie.model.DeviceConfResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceCountResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceInfoResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.DigestRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalDecryptRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalEncryptRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalVerifyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccInternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccInternalVerifyRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExportKekComponentRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileCreateRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileReadRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileWriteRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateAgreementDataAndKeyEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardEccKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardRsaKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacResult; +import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.KekComponentRequest; +import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.LoginStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest; +import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest; +import com.cisd.tms.integration.crypto.pcie.model.RecoverKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPrivateKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPublicKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaInternalKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult; +import com.cisd.tms.integration.crypto.pcie.model.UkeyGenerateRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyLoginRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyPinChangeRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyUnlockRequest; +import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest; +import com.sun.jna.Memory; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.ptr.PointerByReference; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +public class JnaPcieCryptoService implements PcieCryptoService { + + private static final int ECC_KEY_BITS = 256; + private static final int LMK_SEED_MAC_LENGTH = 8; + private static final int HMAC_MAX_LENGTH = 64; + private static final int ECC_CIPHER_PREFIX_LENGTH = (EccRefPublicKey.MAX_LEN * 2) + 32 + Integer.BYTES; + + private final PcieSessionTemplate sessionTemplate; + + public JnaPcieCryptoService(PcieSessionTemplate sessionTemplate) { + this.sessionTemplate = sessionTemplate; + } + + @Override + public DeviceCountResult getDeviceCount() { + return sessionTemplate.withDevice("SDFE_GetDeviceNumber", (lib, deviceHandle) -> { + IntByReference total = new IntByReference(); + sessionTemplate.ensureSuccess("SDFE_GetDeviceNumber", lib.SDFE_GetDeviceNumber(total)); + + IntByReference normal = new IntByReference(); + sessionTemplate.ensureSuccess("SDFE_GetNormalDeviceNumber", lib.SDFE_GetNormalDeviceNumber(deviceHandle, normal)); + + DeviceCountResult result = new DeviceCountResult(); + result.setDeviceNumber(total.getValue()); + result.setNormalDeviceNumber(normal.getValue()); + return result; + }); + } + + @Override + public DeviceConfResult getDeviceConf() { + return sessionTemplate.withSession("SDFE_DeviceConfGet", (lib, deviceHandle, sessionHandle) -> { + SdfeDeviceConf conf = new SdfeDeviceConf(); + sessionTemplate.ensureSuccess("SDFE_DeviceConfGet", lib.SDFE_DeviceConfGet(sessionHandle, conf)); + conf.read(); + + DeviceConfResult result = new DeviceConfResult(); + result.setLevel(conf.level); + result.setDevCount(conf.devCount); + result.setRsaKeyCount(conf.rsaKeyCount); + result.setSm2KeyCount(conf.sm2KeyCount); + result.setKekCount(conf.kekCount); + result.setSessKeyCount(conf.sessKeyCount); + result.setFileSysCapacity(conf.fileSysCapacity); + return result; + }); + } + + @Override + public DeviceInfoResult getDeviceInfo() { + return sessionTemplate.withSession("SDF_GetDeviceInfo", (lib, deviceHandle, sessionHandle) -> { + SdfDeviceInfo info = new SdfDeviceInfo(); + sessionTemplate.ensureSuccess("SDF_GetDeviceInfo", lib.SDF_GetDeviceInfo(sessionHandle, info)); + info.read(); + + DeviceInfoResult result = new DeviceInfoResult(); + result.setIssuerName(zeroTerminatedString(info.issuerName)); + result.setDeviceName(zeroTerminatedString(info.deviceName)); + result.setDeviceSerial(zeroTerminatedString(info.deviceSerial)); + result.setDeviceVersion(info.deviceVersion); + result.setStandardVersion(info.standardVersion); + result.setAsymAlgAbility0(info.asymAlgAbility[0]); + result.setAsymAlgAbility1(info.asymAlgAbility[1]); + result.setSymAlgAbility(info.symAlgAbility); + result.setHashAlgAbility(info.hashAlgAbility); + result.setBufferSize(info.bufferSize); + return result; + }); + } + + @Override + public byte[] generateRandom(int length) { + int randomLength = requirePositive("length", length); + + return sessionTemplate.withSession("SDF_GenerateRandom", (lib, deviceHandle, sessionHandle) -> { + byte[] output = new byte[randomLength]; + sessionTemplate.ensureSuccess("SDF_GenerateRandom", lib.SDF_GenerateRandom(sessionHandle, randomLength, output)); + return output; + }); + } + + @Override + public void initIdentify(byte[] oldPin, byte[] newPin) { + byte[] oldPinValue = requireNonEmptyBytes("oldPin", oldPin); + byte[] newPinValue = requireNonEmptyBytes("newPin", newPin); + + sessionTemplate.withSession("SDFE_InitIdentify", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_InitIdentify", + lib.SDFE_InitIdentify(sessionHandle, oldPinValue, oldPinValue.length, newPinValue, newPinValue.length) + ); + return null; + }); + } + + @Override + public void deviceSelfTest() { + sessionTemplate.withSession("SDFE_DeviceSelfTest", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_DeviceSelfTest", lib.SDFE_DeviceSelfTest(sessionHandle)); + return null; + }); + } + + @Override + public DeviceStatusResult getDeviceStatus(int statusBufferSize) { + int size = requirePositive("statusBufferSize", statusBufferSize); + + return sessionTemplate.withSession("SDFE_DeviceStatusGet", (lib, deviceHandle, sessionHandle) -> { + Memory statusMemory = new Memory(size); + sessionTemplate.ensureSuccess("SDFE_DeviceStatusGet", lib.SDFE_DeviceStatusGet(sessionHandle, statusMemory)); + + DeviceStatusResult result = new DeviceStatusResult(); + result.setLength(size); + result.setStatusData(statusMemory.getByteArray(0, size)); + return result; + }); + } + + @Override + public void deviceFactoryReset() { + sessionTemplate.withSession("SDFE_DeviceFactoryReset", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_DeviceFactoryReset", lib.SDFE_DeviceFactoryReset(sessionHandle)); + return null; + }); + } + + @Override + public void changePrivateKeyAccessPassword(ChangePrivateKeyPasswordRequest request) { + ChangePrivateKeyPasswordRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] oldPassword = requireNonEmptyBytes("oldPassword", req.getOldPassword()); + byte[] newPassword = requireNonEmptyBytes("newPassword", req.getNewPassword()); + + sessionTemplate.withSession("SDFE_ChangePrivateKeyAccessPassword", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ChangePrivateKeyAccessPassword", + lib.SDFE_ChangePrivateKeyAccessPassword( + sessionHandle, + keyIndex, + oldPassword, + oldPassword.length, + newPassword, + newPassword.length + ) + ); + return null; + }); + } + + @Override + public void getPrivateKeyAccessRight(PrivateKeyAccessRequest request) { + PrivateKeyAccessRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] password = requireNonEmptyBytes("password", req.getPassword()); + + sessionTemplate.withSession("SDF_GetPrivateKeyAccessRight", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDF_GetPrivateKeyAccessRight", + lib.SDF_GetPrivateKeyAccessRight(sessionHandle, keyIndex, password, password.length) + ); + return null; + }); + } + + @Override + public void releasePrivateKeyAccessRight(int keyIndex) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + + sessionTemplate.withSession("SDF_ReleasePrivateKeyAccessRight", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDF_ReleasePrivateKeyAccessRight", + lib.SDF_ReleasePrivateKeyAccessRight(sessionHandle, safeKeyIndex) + ); + return null; + }); + } + + @Override + public void generateKeyPairEcc(GenerateKeyPairRequest request) { + GenerateKeyPairRequest req = requireRequest("request", request); + int keyBits = req.getKeyBits(); + if (keyBits != ECC_KEY_BITS) { + throw new IllegalArgumentException("keyBits must be 256 for ECC"); + } + + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int keyType = requireUserKeyType(req.getKeyType()); + + sessionTemplate.withSession("SDFE_GenerateKeyPair_ECC", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_GenerateKeyPair_ECC", + lib.SDFE_GenerateKeyPair_ECC(sessionHandle, keyBits, keyIndex, keyType) + ); + return null; + }); + } + + @Override + public void generateKeyPairRsa(GenerateKeyPairRequest request) { + GenerateKeyPairRequest req = requireRequest("request", request); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int keyType = requireUserKeyType(req.getKeyType()); + + sessionTemplate.withSession("SDFE_GenerateKeyPair_RSA", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_GenerateKeyPair_RSA", + lib.SDFE_GenerateKeyPair_RSA(sessionHandle, keyBits, keyIndex, keyType) + ); + return null; + }); + } + + @Override + public void importKeyPairEcc(ImportKeyPairRequest request) { + ImportKeyPairRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int keyType = requireUserKeyType(req.getKeyType()); + EccRefPublicKey publicKey = toEccRefPublicKey("publicKey", req.getPublicKey()); + EccRefPrivateKey privateKey = toEccRefPrivateKey("privateKey", req.getPrivateKey()); + + sessionTemplate.withSession("SDFE_ImportKeyPair_ECC", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportKeyPair_ECC", + lib.SDFE_ImportKeyPair_ECC(sessionHandle, keyIndex, keyType, publicKey, privateKey) + ); + return null; + }); + } + + @Override + public void importKeyPairRsa(ImportKeyPairRequest request) { + ImportKeyPairRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int keyType = requireUserKeyType(req.getKeyType()); + RsaRefPublicKey publicKey = toRsaRefPublicKey("publicKey", req.getPublicKey()); + RsaRefPrivateKey privateKey = toRsaRefPrivateKey("privateKey", req.getPrivateKey()); + + sessionTemplate.withSession("SDFE_ImportKeyPair_RSA", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportKeyPair_RSA", + lib.SDFE_ImportKeyPair_RSA(sessionHandle, keyIndex, keyType, publicKey, privateKey) + ); + return null; + }); + } + + @Override + public void generateKek(GenerateKekRequest request) { + GenerateKekRequest req = requireRequest("request", request); + int keyBits = req.getKeyBits(); + if (keyBits != 128 && keyBits != 192 && keyBits != 256) { + throw new IllegalArgumentException("keyBits must be one of 128/192/256 for KEK"); + } + + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + + sessionTemplate.withSession("SDFE_GenerateKEK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_GenerateKEK", lib.SDFE_GenerateKEK(sessionHandle, keyBits, keyIndex)); + return null; + }); + } + + @Override + public void importKek(ImportKekRequest request) { + ImportKekRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] keyData = requireNonEmptyBytes("keyData", req.getKeyData()); + + sessionTemplate.withSession("SDFE_ImportKEK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportKEK", + lib.SDFE_ImportKEK(sessionHandle, keyIndex, keyData, keyData.length) + ); + return null; + }); + } + + @Override + public void importKekComponent(KekComponentRequest request) { + KekComponentRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int componentNum = requirePositive("componentNum", req.getComponentNum()); + SdfeKekComponent componentData = toSdfeKekComponent("componentData", req.getComponentData()); + + sessionTemplate.withSession("SDFE_ImportKEKComponent", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportKEKComponent", + lib.SDFE_ImportKEKComponent(sessionHandle, keyIndex, componentNum, componentData) + ); + return null; + }); + } + + @Override + public BackupDataResult exportKekComponent(ExportKekComponentRequest request) { + ExportKekComponentRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int componentNum = requirePositive("componentNum", req.getComponentNum()); + int componentSize = requirePositive("componentSize", req.getComponentSize()); + + return sessionTemplate.withSession("SDFE_ExportKEKComponent", (lib, deviceHandle, sessionHandle) -> { + SdfeKekComponent output = new SdfeKekComponent(); + int structSize = output.size(); + if (componentSize < structSize) { + throw new IllegalArgumentException("componentSize must be >= " + structSize); + } + sessionTemplate.ensureSuccess( + "SDFE_ExportKEKComponent", + lib.SDFE_ExportKEKComponent(sessionHandle, keyIndex, componentNum, output) + ); + return toBackupResult("SDFE_ExportKEKComponent", toBytes(output), structSize); + }); + } + + @Override + public BackupDataResult backupUserKey(int keyIndex, int keyType, int outBufferSize) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int safeKeyType = requireUserKeyType(keyType); + int safeOutBufferSize = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDFE_BackupUserKey", (lib, deviceHandle, sessionHandle) -> { + byte[] out = new byte[safeOutBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess( + "SDFE_BackupUserKey", + lib.SDFE_BackupUserKey(sessionHandle, safeKeyIndex, safeKeyType, out, outLen) + ); + return toBackupResult("SDFE_BackupUserKey", out, outLen.getValue()); + }); + } + + @Override + public void recoverUserKey(RecoverUserKeyRequest request) { + RecoverUserKeyRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int keyType = requireUserKeyType(req.getKeyType()); + byte[] encryptedKey = requireNonEmptyBytes("encryptedKey", req.getEncryptedKey()); + int storeFlag = req.getStoreFlag(); + if (storeFlag != 0 && storeFlag != 1) { + throw new IllegalArgumentException("storeFlag must be 0 or 1"); + } + + sessionTemplate.withSession("SDFE_RecoverUserKey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_RecoverUserKey", + lib.SDFE_RecoverUserKey( + sessionHandle, + keyIndex, + keyType, + encryptedKey, + encryptedKey.length, + (byte) storeFlag + ) + ); + return null; + }); + } + + @Override + public BackupDataResult backupKek(int keyIndex, int outBufferSize) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int safeOutBufferSize = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDFE_BackupKEK", (lib, deviceHandle, sessionHandle) -> { + byte[] out = new byte[safeOutBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess("SDFE_BackupKEK", lib.SDFE_BackupKEK(sessionHandle, safeKeyIndex, out, outLen)); + return toBackupResult("SDFE_BackupKEK", out, outLen.getValue()); + }); + } + + @Override + public void recoverKek(RecoverKekRequest request) { + RecoverKekRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] encryptedKey = requireNonEmptyBytes("encryptedKey", req.getEncryptedKey()); + + sessionTemplate.withSession("SDFE_RecoverKEK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_RecoverKEK", + lib.SDFE_RecoverKEK(sessionHandle, keyIndex, encryptedKey, encryptedKey.length) + ); + return null; + }); + } + + @Override + public void deleteUserKey(int keyIndex) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + + sessionTemplate.withSession("SDFE_DeleteUserKey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_DeleteUserKey", lib.SDFE_DeleteUserKey(sessionHandle, safeKeyIndex)); + return null; + }); + } + + @Override + public void deleteKek(int keyIndex) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + + sessionTemplate.withSession("SDFE_DeleteKey_KEK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_DeleteKey_KEK", lib.SDFE_DeleteKey_KEK(sessionHandle, safeKeyIndex)); + return null; + }); + } + + @Override + public BackupDataResult backupAllKey(int outBufferSize) { + int safeOutBufferSize = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDFE_BackKey", (lib, deviceHandle, sessionHandle) -> { + byte[] out = new byte[safeOutBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess("SDFE_BackKey", lib.SDFE_BackKey(sessionHandle, out, outLen)); + return toBackupResult("SDFE_BackKey", out, outLen.getValue()); + }); + } + + @Override + public void restoreAllKey(byte[] keyImage) { + byte[] safeKeyImage = requireNonEmptyBytes("keyImage", keyImage); + + sessionTemplate.withSession("SDFE_RestoryKey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_RestoryKey", + lib.SDFE_RestoryKey(sessionHandle, safeKeyImage, safeKeyImage.length) + ); + return null; + }); + } + + @Override + public KeyStatusResult statusUserKeyEcc(int keyIndex, int keyType) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int safeKeyType = requireUserKeyType(keyType); + + return sessionTemplate.withSession("SDFE_StatusUserKey_ECC", (lib, deviceHandle, sessionHandle) -> { + IntByReference stateRef = new IntByReference(); + sessionTemplate.ensureSuccess( + "SDFE_StatusUserKey_ECC", + lib.SDFE_StatusUserKey_ECC(sessionHandle, safeKeyIndex, safeKeyType, stateRef) + ); + return toKeyStatus(stateRef.getValue()); + }); + } + + @Override + public KeyStatusResult statusUserKeyRsa(int keyIndex, int keyType) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int safeKeyType = requireUserKeyType(keyType); + + return sessionTemplate.withSession("SDFE_StatusUserKey_RSA", (lib, deviceHandle, sessionHandle) -> { + IntByReference stateRef = new IntByReference(); + sessionTemplate.ensureSuccess( + "SDFE_StatusUserKey_RSA", + lib.SDFE_StatusUserKey_RSA(sessionHandle, safeKeyIndex, safeKeyType, stateRef) + ); + return toKeyStatus(stateRef.getValue()); + }); + } + + @Override + public KeyStatusResult statusKek(int keyIndex) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + + return sessionTemplate.withSession("SDFE_StatusKey_KEK", (lib, deviceHandle, sessionHandle) -> { + IntByReference stateRef = new IntByReference(); + sessionTemplate.ensureSuccess("SDFE_StatusKey_KEK", lib.SDFE_StatusKey_KEK(sessionHandle, safeKeyIndex, stateRef)); + return toKeyStatus(stateRef.getValue()); + }); + } + + @Override + public void importEncryptedKeyPairEcc(ImportEncKeyPairEccRequest request) { + ImportEncKeyPairEccRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + EnvelopedKeyBlob blob = toEnvelopedKeyBlob("envelopedKeyBlob", req.getEnvelopedKeyBlob()); + + sessionTemplate.withSession("SDFE_ImportEncKeyPair_ECC", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportEncKeyPair_ECC", + lib.SDFE_ImportEncKeyPair_ECC(sessionHandle, keyIndex, blob) + ); + return null; + }); + } + + @Override + public void importEncryptedKeyPairRsa(ImportEncKeyPairRsaRequest request) { + ImportEncKeyPairRsaRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int symAlgId = requirePositive("symAlgId", req.getSymAlgId()); + byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + byte[] encryptedData = requireNonEmptyBytes("encryptedData", req.getEncryptedData()); + + sessionTemplate.withSession("SDFE_ImportEncKeyPair_RSA", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ImportEncKeyPair_RSA", + lib.SDFE_ImportEncKeyPair_RSA( + sessionHandle, + keyIndex, + symAlgId, + wrappedKey, + wrappedKey.length, + encryptedData, + encryptedData.length + ) + ); + return null; + }); + } + + @Override + public BackupDataResult updateBackedKey(UpdateBackedKeyRequest request) { + UpdateBackedKeyRequest req = requireRequest("request", request); + byte[] oldData = requireNonEmptyBytes("oldData", req.getOldData()); + int bufferSize = requirePositive("newDataBufferSize", req.getNewDataBufferSize()); + + return sessionTemplate.withSession("SDFE_UpdateBackedKey", (lib, deviceHandle, sessionHandle) -> { + byte[] newData = new byte[bufferSize]; + IntByReference newLength = new IntByReference(newData.length); + sessionTemplate.ensureSuccess( + "SDFE_UpdateBackedKey", + lib.SDFE_UpdateBackedKey(sessionHandle, oldData, oldData.length, newData, newLength) + ); + return toBackupResult("SDFE_UpdateBackedKey", newData, newLength.getValue()); + }); + } + + @Override + public BackupDataResult exportSignPublicKeyRsa(int keyIndex, int outBufferSize) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDF_ExportSignPublicKey_RSA", (lib, deviceHandle, sessionHandle) -> { + RsaRefPublicKey out = new RsaRefPublicKey(); + if (size < out.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + out.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExportSignPublicKey_RSA", + lib.SDF_ExportSignPublicKey_RSA(sessionHandle, safeKeyIndex, out) + ); + byte[] outBytes = toBytes(out); + return toBackupResult("SDF_ExportSignPublicKey_RSA", outBytes, outBytes.length); + }); + } + + @Override + public BackupDataResult exportEncPublicKeyRsa(int keyIndex, int outBufferSize) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDF_ExportEncPublicKey_RSA", (lib, deviceHandle, sessionHandle) -> { + RsaRefPublicKey out = new RsaRefPublicKey(); + if (size < out.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + out.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExportEncPublicKey_RSA", + lib.SDF_ExportEncPublicKey_RSA(sessionHandle, safeKeyIndex, out) + ); + byte[] outBytes = toBytes(out); + return toBackupResult("SDF_ExportEncPublicKey_RSA", outBytes, outBytes.length); + }); + } + + @Override + public BackupDataResult exportSignPublicKeyEcc(int keyIndex, int outBufferSize) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDF_ExportSignPublicKey_ECC", (lib, deviceHandle, sessionHandle) -> { + EccRefPublicKey out = new EccRefPublicKey(); + if (size < out.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + out.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExportSignPublicKey_ECC", + lib.SDF_ExportSignPublicKey_ECC(sessionHandle, safeKeyIndex, out) + ); + byte[] outBytes = toBytes(out); + return toBackupResult("SDF_ExportSignPublicKey_ECC", outBytes, outBytes.length); + }); + } + + @Override + public BackupDataResult exportEncPublicKeyEcc(int keyIndex, int outBufferSize) { + int safeKeyIndex = requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDF_ExportEncPublicKey_ECC", (lib, deviceHandle, sessionHandle) -> { + EccRefPublicKey out = new EccRefPublicKey(); + if (size < out.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + out.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExportEncPublicKey_ECC", + lib.SDF_ExportEncPublicKey_ECC(sessionHandle, safeKeyIndex, out) + ); + byte[] outBytes = toBytes(out); + return toBackupResult("SDF_ExportEncPublicKey_ECC", outBytes, outBytes.length); + }); + } + + @Override + public StandardKeyPairResult generateStandardRsaKeyPair(GenerateStandardRsaKeyPairRequest request) { + GenerateStandardRsaKeyPairRequest req = requireRequest("request", request); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int publicKeySize = requirePositive("publicKeyBufferSize", req.getPublicKeyBufferSize()); + int privateKeySize = requirePositive("privateKeyBufferSize", req.getPrivateKeyBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyPair_RSA", (lib, deviceHandle, sessionHandle) -> { + RsaRefPublicKey publicKey = new RsaRefPublicKey(); + RsaRefPrivateKey privateKey = new RsaRefPrivateKey(); + if (publicKeySize < publicKey.size()) { + throw new IllegalArgumentException("publicKeyBufferSize must be >= " + publicKey.size()); + } + if (privateKeySize < privateKey.size()) { + throw new IllegalArgumentException("privateKeyBufferSize must be >= " + privateKey.size()); + } + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyPair_RSA", + lib.SDF_GenerateKeyPair_RSA(sessionHandle, keyBits, publicKey, privateKey) + ); + return toStandardKeyPairResult(toBytes(publicKey), toBytes(privateKey)); + }); + } + + @Override + public StandardKeyPairResult generateStandardEccKeyPair(GenerateStandardEccKeyPairRequest request) { + GenerateStandardEccKeyPairRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int publicKeySize = requirePositive("publicKeyBufferSize", req.getPublicKeyBufferSize()); + int privateKeySize = requirePositive("privateKeyBufferSize", req.getPrivateKeyBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyPair_ECC", (lib, deviceHandle, sessionHandle) -> { + EccRefPublicKey publicKey = new EccRefPublicKey(); + EccRefPrivateKey privateKey = new EccRefPrivateKey(); + if (publicKeySize < publicKey.size()) { + throw new IllegalArgumentException("publicKeyBufferSize must be >= " + publicKey.size()); + } + if (privateKeySize < privateKey.size()) { + throw new IllegalArgumentException("privateKeyBufferSize must be >= " + privateKey.size()); + } + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyPair_ECC", + lib.SDF_GenerateKeyPair_ECC(sessionHandle, algId, keyBits, publicKey, privateKey) + ); + return toStandardKeyPairResult(toBytes(publicKey), toBytes(privateKey)); + }); + } + + @Override + public BackupDataResult generateKeyWithKek(GenerateKeyWithKekRequest request) { + GenerateKeyWithKekRequest req = requireRequest("request", request); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int algId = requirePositive("algId", req.getAlgId()); + int kekIndex = requireNonNegative("kekIndex", req.getKekIndex()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyWithKEK", (lib, deviceHandle, sessionHandle) -> { + byte[] wrappedKey = new byte[outBufferSize]; + IntByReference wrappedKeyLen = new IntByReference(wrappedKey.length); + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyWithKEK", + lib.SDF_GenerateKeyWithKEK( + sessionHandle, + keyBits, + algId, + kekIndex, + wrappedKey, + wrappedKeyLen, + keyHandleRef + ) + ); + try { + return toBackupResult("SDF_GenerateKeyWithKEK", wrappedKey, wrappedKeyLen.getValue()); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public BackupDataResult rsaExternalPublicKeyOperation(RsaExternalPublicKeyOpRequest request) { + RsaExternalPublicKeyOpRequest req = requireRequest("request", request); + RsaRefPublicKey publicKey = toRsaRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + byte[] input = requireBytes("input", req.getInput()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_ExternalPublicKeyOperation_RSA", (lib, deviceHandle, sessionHandle) -> { + byte[] output = new byte[outBufferSize]; + IntByReference outputLen = new IntByReference(output.length); + sessionTemplate.ensureSuccess( + "SDF_ExternalPublicKeyOperation_RSA", + lib.SDF_ExternalPublicKeyOperation_RSA( + sessionHandle, + publicKey, + input, + input.length, + output, + outputLen + ) + ); + return toBackupResult("SDF_ExternalPublicKeyOperation_RSA", output, outputLen.getValue()); + }); + } + + @Override + public BackupDataResult rsaExternalPrivateKeyOperation(RsaExternalPrivateKeyOpRequest request) { + RsaExternalPrivateKeyOpRequest req = requireRequest("request", request); + RsaRefPrivateKey privateKey = toRsaRefPrivateKey("privateKeyBlob", req.getPrivateKeyBlob()); + byte[] input = requireBytes("input", req.getInput()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_ExternalPrivateKeyOperation_RSA", (lib, deviceHandle, sessionHandle) -> { + byte[] output = new byte[outBufferSize]; + IntByReference outputLen = new IntByReference(output.length); + sessionTemplate.ensureSuccess( + "SDF_ExternalPrivateKeyOperation_RSA", + lib.SDF_ExternalPrivateKeyOperation_RSA( + sessionHandle, + privateKey, + input, + input.length, + output, + outputLen + ) + ); + return toBackupResult("SDF_ExternalPrivateKeyOperation_RSA", output, outputLen.getValue()); + }); + } + + @Override + public BackupDataResult rsaInternalPublicKeyOperation(RsaInternalKeyOpRequest request) { + RsaInternalKeyOpRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] input = requireBytes("input", req.getInput()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_InternalPublicKeyOperation_RSA", (lib, deviceHandle, sessionHandle) -> { + byte[] output = new byte[outBufferSize]; + IntByReference outputLen = new IntByReference(output.length); + sessionTemplate.ensureSuccess( + "SDF_InternalPublicKeyOperation_RSA", + lib.SDF_InternalPublicKeyOperation_RSA( + sessionHandle, + keyIndex, + input, + input.length, + output, + outputLen + ) + ); + return toBackupResult("SDF_InternalPublicKeyOperation_RSA", output, outputLen.getValue()); + }); + } + + @Override + public BackupDataResult rsaInternalPrivateKeyOperation(RsaInternalKeyOpRequest request) { + RsaInternalKeyOpRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] input = requireBytes("input", req.getInput()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_InternalPrivateKeyOperation_RSA", (lib, deviceHandle, sessionHandle) -> { + byte[] output = new byte[outBufferSize]; + IntByReference outputLen = new IntByReference(output.length); + sessionTemplate.ensureSuccess( + "SDF_InternalPrivateKeyOperation_RSA", + lib.SDF_InternalPrivateKeyOperation_RSA( + sessionHandle, + keyIndex, + input, + input.length, + output, + outputLen + ) + ); + return toBackupResult("SDF_InternalPrivateKeyOperation_RSA", output, outputLen.getValue()); + }); + } + + @Override + public BackupDataResult generateKeyWithIpkRsa(GenerateKeyWithIpkRsaRequest request) { + GenerateKeyWithIpkRsaRequest req = requireRequest("request", request); + int ipkIndex = requireNonNegative("ipkIndex", req.getIpkIndex()); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyWithIPK_RSA", (lib, deviceHandle, sessionHandle) -> { + byte[] wrappedKey = new byte[outBufferSize]; + IntByReference wrappedKeyLen = new IntByReference(wrappedKey.length); + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyWithIPK_RSA", + lib.SDF_GenerateKeyWithIPK_RSA( + sessionHandle, + ipkIndex, + keyBits, + wrappedKey, + wrappedKeyLen, + keyHandleRef + ) + ); + try { + return toBackupResult("SDF_GenerateKeyWithIPK_RSA", wrappedKey, wrappedKeyLen.getValue()); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public BackupDataResult generateKeyWithEpkRsa(GenerateKeyWithEpkRsaRequest request) { + GenerateKeyWithEpkRsaRequest req = requireRequest("request", request); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + RsaRefPublicKey publicKeyBlob = toRsaRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyWithEPK_RSA", (lib, deviceHandle, sessionHandle) -> { + byte[] wrappedKey = new byte[outBufferSize]; + IntByReference wrappedKeyLen = new IntByReference(wrappedKey.length); + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyWithEPK_RSA", + lib.SDF_GenerateKeyWithEPK_RSA( + sessionHandle, + keyBits, + publicKeyBlob, + wrappedKey, + wrappedKeyLen, + keyHandleRef + ) + ); + try { + return toBackupResult("SDF_GenerateKeyWithEPK_RSA", wrappedKey, wrappedKeyLen.getValue()); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public void importKeyWithIskRsa(ImportKeyWithIskRsaRequest request) { + ImportKeyWithIskRsaRequest req = requireRequest("request", request); + int iskIndex = requireNonNegative("iskIndex", req.getIskIndex()); + byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + + sessionTemplate.withSession("SDF_ImportKeyWithISK_RSA", (lib, deviceHandle, sessionHandle) -> { + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_ImportKeyWithISK_RSA", + lib.SDF_ImportKeyWithISK_RSA( + sessionHandle, + iskIndex, + wrappedKey, + wrappedKey.length, + keyHandleRef + ) + ); + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + return null; + }); + } + + @Override + public BackupDataResult generateKeyWithIpkEcc(GenerateKeyWithIpkEccRequest request) { + GenerateKeyWithIpkEccRequest req = requireRequest("request", request); + int ipkIndex = requireNonNegative("ipkIndex", req.getIpkIndex()); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyWithIPK_ECC", (lib, deviceHandle, sessionHandle) -> { + EccCipher encryptedKey = new EccCipher(); + if (outBufferSize < encryptedKey.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + encryptedKey.size()); + } + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyWithIPK_ECC", + lib.SDF_GenerateKeyWithIPK_ECC( + sessionHandle, + ipkIndex, + keyBits, + encryptedKey, + keyHandleRef + ) + ); + try { + byte[] outBytes = toEccCipherBytes("SDF_GenerateKeyWithIPK_ECC", encryptedKey); + return toBackupResult("SDF_GenerateKeyWithIPK_ECC", outBytes, outBytes.length); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public BackupDataResult generateKeyWithEpkEcc(GenerateKeyWithEpkEccRequest request) { + GenerateKeyWithEpkEccRequest req = requireRequest("request", request); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + int algId = requirePositive("algId", req.getAlgId()); + EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateKeyWithEPK_ECC", (lib, deviceHandle, sessionHandle) -> { + EccCipher encryptedKey = new EccCipher(); + if (outBufferSize < encryptedKey.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + encryptedKey.size()); + } + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyWithEPK_ECC", + lib.SDF_GenerateKeyWithEPK_ECC( + sessionHandle, + keyBits, + algId, + publicKeyBlob, + encryptedKey, + keyHandleRef + ) + ); + try { + byte[] outBytes = toEccCipherBytes("SDF_GenerateKeyWithEPK_ECC", encryptedKey); + return toBackupResult("SDF_GenerateKeyWithEPK_ECC", outBytes, outBytes.length); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public void importKeyWithIskEcc(ImportKeyWithIskEccRequest request) { + ImportKeyWithIskEccRequest req = requireRequest("request", request); + int iskIndex = requireNonNegative("iskIndex", req.getIskIndex()); + EccCipher encryptedKeyBlob = toEccCipher("encryptedKeyBlob", req.getEncryptedKeyBlob()); + + sessionTemplate.withSession("SDF_ImportKeyWithISK_ECC", (lib, deviceHandle, sessionHandle) -> { + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_ImportKeyWithISK_ECC", + lib.SDF_ImportKeyWithISK_ECC(sessionHandle, iskIndex, encryptedKeyBlob, keyHandleRef) + ); + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + return null; + }); + } + + @Override + public BackupDataResult exchangeDigitEnvelopeBaseOnRsa(ExchangeDigitEnvelopeRsaRequest request) { + ExchangeDigitEnvelopeRsaRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + RsaRefPublicKey publicKeyBlob = toRsaRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + byte[] inputEnvelopeBlob = requireNonEmptyBytes("inputEnvelopeBlob", req.getInputEnvelopeBlob()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_ExchangeDigitEnvelopeBaseOnRSA", (lib, deviceHandle, sessionHandle) -> { + byte[] outputEnvelopeBlob = new byte[outBufferSize]; + IntByReference outputEnvelopeLength = new IntByReference(outputEnvelopeBlob.length); + sessionTemplate.ensureSuccess( + "SDF_ExchangeDigitEnvelopeBaseOnRSA", + lib.SDF_ExchangeDigitEnvelopeBaseOnRSA( + sessionHandle, + keyIndex, + publicKeyBlob, + inputEnvelopeBlob, + inputEnvelopeBlob.length, + outputEnvelopeBlob, + outputEnvelopeLength + ) + ); + return toBackupResult("SDF_ExchangeDigitEnvelopeBaseOnRSA", outputEnvelopeBlob, outputEnvelopeLength.getValue()); + }); + } + + @Override + public BackupDataResult exchangeDigitEnvelopeBaseOnEcc(ExchangeDigitEnvelopeEccRequest request) { + ExchangeDigitEnvelopeEccRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + int algId = requirePositive("algId", req.getAlgId()); + EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + EccCipher inputEnvelopeBlob = toEccCipher("inputEnvelopeBlob", req.getInputEnvelopeBlob()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_ExchangeDigitEnvelopeBaseOnECC", (lib, deviceHandle, sessionHandle) -> { + EccCipher outputEnvelopeBlob = new EccCipher(); + if (outBufferSize < outputEnvelopeBlob.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + outputEnvelopeBlob.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExchangeDigitEnvelopeBaseOnECC", + lib.SDF_ExchangeDigitEnvelopeBaseOnECC( + sessionHandle, + keyIndex, + algId, + publicKeyBlob, + inputEnvelopeBlob, + outputEnvelopeBlob + ) + ); + byte[] outBytes = toEccCipherBytes("SDF_ExchangeDigitEnvelopeBaseOnECC", outputEnvelopeBlob); + return toBackupResult("SDF_ExchangeDigitEnvelopeBaseOnECC", outBytes, outBytes.length); + }); + } + + @Override + public AgreementDataAndKeyEccResult generateAgreementDataAndKeyWithEcc(GenerateAgreementDataAndKeyEccRequest request) { + GenerateAgreementDataAndKeyEccRequest req = requireRequest("request", request); + int iskIndex = requireNonNegative("iskIndex", req.getIskIndex()); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + byte[] responseId = requireNonEmptyBytes("responseId", req.getResponseId()); + byte[] sponsorId = requireNonEmptyBytes("sponsorId", req.getSponsorId()); + EccRefPublicKey sponsorPublicKey = toEccRefPublicKey("sponsorPublicKeyBlob", req.getSponsorPublicKeyBlob()); + EccRefPublicKey sponsorTmpPublicKey = toEccRefPublicKey("sponsorTmpPublicKeyBlob", req.getSponsorTmpPublicKeyBlob()); + int responsePublicKeySize = requirePositive("responsePublicKeyBufferSize", req.getResponsePublicKeyBufferSize()); + int responseTmpPublicKeySize = requirePositive("responseTmpPublicKeyBufferSize", req.getResponseTmpPublicKeyBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateAgreementDataAndKeyWithECC", (lib, deviceHandle, sessionHandle) -> { + EccRefPublicKey responsePublicKey = new EccRefPublicKey(); + EccRefPublicKey responseTmpPublicKey = new EccRefPublicKey(); + if (responsePublicKeySize < responsePublicKey.size()) { + throw new IllegalArgumentException("responsePublicKeyBufferSize must be >= " + responsePublicKey.size()); + } + if (responseTmpPublicKeySize < responseTmpPublicKey.size()) { + throw new IllegalArgumentException("responseTmpPublicKeyBufferSize must be >= " + responseTmpPublicKey.size()); + } + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateAgreementDataAndKeyWithECC", + lib.SDF_GenerateAgreementDataAndKeyWithECC( + sessionHandle, + iskIndex, + keyBits, + responseId, + responseId.length, + sponsorId, + sponsorId.length, + sponsorPublicKey, + sponsorTmpPublicKey, + responsePublicKey, + responseTmpPublicKey, + keyHandleRef + ) + ); + try { + AgreementDataAndKeyEccResult result = new AgreementDataAndKeyEccResult(); + byte[] responsePublicKeyBytes = toBytes(responsePublicKey); + byte[] responseTmpPublicKeyBytes = toBytes(responseTmpPublicKey); + result.setResponsePublicKey(responsePublicKeyBytes); + result.setResponsePublicKeyLength(responsePublicKeyBytes.length); + result.setResponseTmpPublicKey(responseTmpPublicKeyBytes); + result.setResponseTmpPublicKeyLength(responseTmpPublicKeyBytes.length); + result.setSessionKeyGenerated(keyHandleRef.getValue() != null); + return result; + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public EccAgreementSessionKeyResult generateSessionKeyWithEccAgreement(EccAgreementSessionKeyRequest request) { + EccAgreementSessionKeyRequest req = requireRequest("request", request); + int iskIndex = requireNonNegative("iskIndex", req.getIskIndex()); + int keyBits = requirePositive("keyBits", req.getKeyBits()); + byte[] sponsorId = requireNonEmptyBytes("sponsorId", req.getSponsorId()); + byte[] responseId = requireNonEmptyBytes("responseId", req.getResponseId()); + EccRefPublicKey responsePublicKey = toEccRefPublicKey("responsePublicKeyBlob", req.getResponsePublicKeyBlob()); + EccRefPublicKey responseTmpPublicKey = toEccRefPublicKey("responseTmpPublicKeyBlob", req.getResponseTmpPublicKeyBlob()); + int sponsorPublicKeySize = requirePositive("sponsorPublicKeyBufferSize", req.getSponsorPublicKeyBufferSize()); + int sponsorTmpPublicKeySize = requirePositive("sponsorTmpPublicKeyBufferSize", req.getSponsorTmpPublicKeyBufferSize()); + requirePositive("sessionKeyBufferSize", req.getSessionKeyBufferSize()); + + return sessionTemplate.withSession("SDF_GenerateAgreementDataWithECC+SDF_GenerateKeyWithECC", (lib, deviceHandle, sessionHandle) -> { + EccRefPublicKey sponsorPublicKey = new EccRefPublicKey(); + EccRefPublicKey sponsorTmpPublicKey = new EccRefPublicKey(); + if (sponsorPublicKeySize < sponsorPublicKey.size()) { + throw new IllegalArgumentException("sponsorPublicKeyBufferSize must be >= " + sponsorPublicKey.size()); + } + if (sponsorTmpPublicKeySize < sponsorTmpPublicKey.size()) { + throw new IllegalArgumentException("sponsorTmpPublicKeyBufferSize must be >= " + sponsorTmpPublicKey.size()); + } + PointerByReference agreementHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_GenerateAgreementDataWithECC", + lib.SDF_GenerateAgreementDataWithECC( + sessionHandle, + iskIndex, + keyBits, + sponsorId, + sponsorId.length, + sponsorPublicKey, + sponsorTmpPublicKey, + agreementHandleRef + ) + ); + + Pointer agreementHandle = agreementHandleRef.getValue(); + if (agreementHandle == null) { + throw new PcieCryptoException("SDF_GenerateAgreementDataWithECC", -1, "native returned null agreement handle"); + } + + PointerByReference keyHandleRef = new PointerByReference(); + + sessionTemplate.ensureSuccess( + "SDF_GenerateKeyWithECC", + lib.SDF_GenerateKeyWithECC( + sessionHandle, + responseId, + responseId.length, + responsePublicKey, + responseTmpPublicKey, + agreementHandle, + keyHandleRef + ) + ); + + try { + EccAgreementSessionKeyResult result = new EccAgreementSessionKeyResult(); + byte[] sponsorPublicKeyBytes = toBytes(sponsorPublicKey); + byte[] sponsorTmpPublicKeyBytes = toBytes(sponsorTmpPublicKey); + result.setSponsorPublicKey(sponsorPublicKeyBytes); + result.setSponsorPublicKeyLength(sponsorPublicKeyBytes.length); + result.setSponsorTmpPublicKey(sponsorTmpPublicKeyBytes); + result.setSponsorTmpPublicKeyLength(sponsorTmpPublicKeyBytes.length); + result.setSessionKey(new byte[0]); + result.setSessionKeyLength(0); + result.setSessionKeyGenerated(keyHandleRef.getValue() != null); + return result; + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandleRef.getValue()); + } + }); + } + + @Override + public BackupDataResult eccInternalSign(EccInternalSignRequest request) { + EccInternalSignRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] data = requireBytes("data", req.getData()); + int signatureBufferSize = requirePositive("signatureBufferSize", req.getSignatureBufferSize()); + + return sessionTemplate.withSession("SDF_InternalSign_ECC", (lib, deviceHandle, sessionHandle) -> { + EccSignature signature = new EccSignature(); + if (signatureBufferSize < signature.size()) { + throw new IllegalArgumentException("signatureBufferSize must be >= " + signature.size()); + } + sessionTemplate.ensureSuccess( + "SDF_InternalSign_ECC", + lib.SDF_InternalSign_ECC(sessionHandle, keyIndex, data, data.length, signature) + ); + byte[] signatureBytes = toBytes(signature); + return toBackupResult("SDF_InternalSign_ECC", signatureBytes, signatureBytes.length); + }); + } + + @Override + public BackupDataResult eccExternalSign(EccExternalSignRequest request) { + EccExternalSignRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + EccRefPrivateKey privateKeyBlob = toEccRefPrivateKey("privateKeyBlob", req.getPrivateKeyBlob()); + byte[] data = requireBytes("data", req.getData()); + int signatureBufferSize = requirePositive("signatureBufferSize", req.getSignatureBufferSize()); + + return sessionTemplate.withSession("SDF_ExternalSign_ECC", (lib, deviceHandle, sessionHandle) -> { + EccSignature signature = new EccSignature(); + if (signatureBufferSize < signature.size()) { + throw new IllegalArgumentException("signatureBufferSize must be >= " + signature.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExternalSign_ECC", + lib.SDF_ExternalSign_ECC(sessionHandle, algId, privateKeyBlob, data, data.length, signature) + ); + byte[] signatureBytes = toBytes(signature); + return toBackupResult("SDF_ExternalSign_ECC", signatureBytes, signatureBytes.length); + }); + } + + @Override + public void eccInternalVerify(EccInternalVerifyRequest request) { + EccInternalVerifyRequest req = requireRequest("request", request); + int keyIndex = requireNonNegative("keyIndex", req.getKeyIndex()); + byte[] data = requireBytes("data", req.getData()); + EccSignature signature = toEccSignature("signature", req.getSignature()); + + sessionTemplate.withSession("SDF_InternalVerify_ECC", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDF_InternalVerify_ECC", + lib.SDF_InternalVerify_ECC(sessionHandle, keyIndex, data, data.length, signature) + ); + return null; + }); + } + + @Override + public void eccExternalVerify(EccExternalVerifyRequest request) { + EccExternalVerifyRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + byte[] data = requireBytes("data", req.getData()); + EccSignature signature = toEccSignature("signature", req.getSignature()); + + sessionTemplate.withSession("SDF_ExternalVerify_ECC", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDF_ExternalVerify_ECC", + lib.SDF_ExternalVerify_ECC(sessionHandle, algId, publicKeyBlob, data, data.length, signature) + ); + return null; + }); + } + + @Override + public BackupDataResult eccExternalEncrypt(EccExternalEncryptRequest request) { + EccExternalEncryptRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + EccRefPublicKey publicKeyBlob = toEccRefPublicKey("publicKeyBlob", req.getPublicKeyBlob()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_ExternalEncrypt_ECC", (lib, deviceHandle, sessionHandle) -> { + EccCipher encrypted = new EccCipher(); + if (outBufferSize < encrypted.size()) { + throw new IllegalArgumentException("outBufferSize must be >= " + encrypted.size()); + } + sessionTemplate.ensureSuccess( + "SDF_ExternalEncrypt_ECC", + lib.SDF_ExternalEncrypt_ECC(sessionHandle, algId, publicKeyBlob, data, data.length, encrypted) + ); + byte[] encryptedBytes = toEccCipherBytes("SDF_ExternalEncrypt_ECC", encrypted); + return toBackupResult("SDF_ExternalEncrypt_ECC", encryptedBytes, encryptedBytes.length); + }); + } + + @Override + public BackupDataResult eccExternalDecrypt(EccExternalDecryptRequest request) { + EccExternalDecryptRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + EccRefPrivateKey privateKeyBlob = toEccRefPrivateKey("privateKeyBlob", req.getPrivateKeyBlob()); + EccCipher encryptedData = toEccCipher("encryptedData", req.getEncryptedData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_ExternalDecrypt_ECC", (lib, deviceHandle, sessionHandle) -> { + byte[] plain = new byte[outBufferSize]; + IntByReference plainLen = new IntByReference(plain.length); + sessionTemplate.ensureSuccess( + "SDF_ExternalDecrypt_ECC", + lib.SDF_ExternalDecrypt_ECC(sessionHandle, algId, privateKeyBlob, encryptedData, plain, plainLen) + ); + return toBackupResult("SDF_ExternalDecrypt_ECC", plain, plainLen.getValue()); + }); + } + + @Override + public BackupDataResult encryptWithPlainKey(SymmetricCryptoRequest request) { + SymmetricCryptoRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + byte[] key = requireNonEmptyBytes("key", req.getKey()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + byte[] iv = req.getIv(); + + return sessionTemplate.withSession("SDF_Encrypt", (lib, deviceHandle, sessionHandle) -> + withImportedPlainKey(lib, sessionHandle, key, handle -> { + byte[] out = new byte[outBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess( + "SDF_Encrypt", + lib.SDF_Encrypt(sessionHandle, handle, algId, iv, data, data.length, out, outLen) + ); + return toBackupResult("SDF_Encrypt", out, outLen.getValue()); + }) + ); + } + + @Override + public BackupDataResult decryptWithPlainKey(SymmetricCryptoRequest request) { + SymmetricCryptoRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + byte[] key = requireNonEmptyBytes("key", req.getKey()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + byte[] iv = req.getIv(); + + return sessionTemplate.withSession("SDF_Decrypt", (lib, deviceHandle, sessionHandle) -> + withImportedPlainKey(lib, sessionHandle, key, handle -> { + byte[] out = new byte[outBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess( + "SDF_Decrypt", + lib.SDF_Decrypt(sessionHandle, handle, algId, iv, data, data.length, out, outLen) + ); + return toBackupResult("SDF_Decrypt", out, outLen.getValue()); + }) + ); + } + + @Override + public BackupDataResult encryptWithKekWrappedKey(SymmetricKekCryptoRequest request) { + SymmetricKekCryptoRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + int kekIndex = requireNonNegative("kekIndex", req.getKekIndex()); + byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + byte[] iv = req.getIv(); + + return sessionTemplate.withSession("SDF_Encrypt", (lib, deviceHandle, sessionHandle) -> + withImportedKekKey(lib, sessionHandle, algId, kekIndex, wrappedKey, handle -> { + byte[] out = new byte[outBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess( + "SDF_Encrypt", + lib.SDF_Encrypt(sessionHandle, handle, algId, iv, data, data.length, out, outLen) + ); + return toBackupResult("SDF_Encrypt", out, outLen.getValue()); + }) + ); + } + + @Override + public BackupDataResult decryptWithKekWrappedKey(SymmetricKekCryptoRequest request) { + SymmetricKekCryptoRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + int kekIndex = requireNonNegative("kekIndex", req.getKekIndex()); + byte[] wrappedKey = requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + byte[] iv = req.getIv(); + + return sessionTemplate.withSession("SDF_Decrypt", (lib, deviceHandle, sessionHandle) -> + withImportedKekKey(lib, sessionHandle, algId, kekIndex, wrappedKey, handle -> { + byte[] out = new byte[outBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess( + "SDF_Decrypt", + lib.SDF_Decrypt(sessionHandle, handle, algId, iv, data, data.length, out, outLen) + ); + return toBackupResult("SDF_Decrypt", out, outLen.getValue()); + }) + ); + } + + @Override + public BackupDataResult calculateMacWithPlainKey(MacCalcRequest request) { + MacCalcRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + byte[] key = requireNonEmptyBytes("key", req.getKey()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + byte[] iv = req.getIv(); + + return sessionTemplate.withSession("SDF_CalculateMAC", (lib, deviceHandle, sessionHandle) -> + withImportedPlainKey(lib, sessionHandle, key, handle -> { + byte[] out = new byte[outBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess( + "SDF_CalculateMAC", + lib.SDF_CalculateMAC(sessionHandle, handle, algId, iv, data, data.length, out, outLen) + ); + return toBackupResult("SDF_CalculateMAC", out, outLen.getValue()); + }) + ); + } + + @Override + public BackupDataResult digest(DigestRequest request) { + DigestRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + byte[] data = requireBytes("data", req.getData()); + int outBufferSize = requirePositive("outBufferSize", req.getOutBufferSize()); + + return sessionTemplate.withSession("SDF_Hash", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDF_HashInit", lib.SDF_HashInit(sessionHandle, algId, null, null, 0)); + if (data.length > 0) { + sessionTemplate.ensureSuccess("SDF_HashUpdate", lib.SDF_HashUpdate(sessionHandle, data, data.length)); + } + byte[] out = new byte[outBufferSize]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess("SDF_HashFinal", lib.SDF_HashFinal(sessionHandle, out, outLen)); + return toBackupResult("SDF_HashFinal", out, outLen.getValue()); + }); + } + + @Override + public HmacResult hmac(HmacRequest request) { + HmacRequest req = requireRequest("request", request); + int algId = requirePositive("algId", req.getAlgId()); + byte[] key = requireNonEmptyBytes("key", req.getKey()); + byte[] data = requireBytes("data", req.getData()); + + return sessionTemplate.withSession("SDFE_Hmac", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_HmacInit", lib.SDFE_HmacInit(sessionHandle, algId, key, key.length)); + if (data.length > 0) { + sessionTemplate.ensureSuccess("SDFE_HmacUpdate", lib.SDFE_HmacUpdate(sessionHandle, data, data.length)); + } + + byte[] out = new byte[HMAC_MAX_LENGTH]; + IntByReference outLen = new IntByReference(out.length); + sessionTemplate.ensureSuccess("SDFE_HmacFinal", lib.SDFE_HmacFinal(sessionHandle, out, outLen)); + + int length = outLen.getValue(); + if (length <= 0 || length > out.length) { + throw new PcieCryptoException("SDFE_HmacFinal", -1, "native returned invalid HMAC length: " + length); + } + + HmacResult result = new HmacResult(); + result.setHmacLength(length); + result.setHmac(Arrays.copyOf(out, length)); + return result; + }); + } + + @Override + public void generateLmk() { + sessionTemplate.withSession("SDFE_GenerateLMK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_GenerateLMK", lib.SDFE_GenerateLMK(sessionHandle)); + return null; + }); + } + + @Override + public void loadLmk() { + sessionTemplate.withSession("SDFE_LoadLMK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_LoadLMK", lib.SDFE_LoadLMK(sessionHandle)); + return null; + }); + } + + @Override + public void backupLmk() { + sessionTemplate.withSession("SDFE_BackupLMK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_BackupLMK", lib.SDFE_BackupLMK(sessionHandle)); + return null; + }); + } + + @Override + public void recoverLmk() { + sessionTemplate.withSession("SDFE_RecoverLMK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_RecoverLMK", lib.SDFE_RecoverLMK(sessionHandle)); + return null; + }); + } + + @Override + public void destroyLmk() { + sessionTemplate.withSession("SDFE_DestroyLMK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_DestroyLMK", lib.SDFE_DestroyLMK(sessionHandle)); + return null; + }); + } + + @Override + public void checkLmk() { + sessionTemplate.withSession("SDFE_CheckLMK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_CheckLMK", lib.SDFE_CheckLMK(sessionHandle)); + return null; + }); + } + + @Override + public byte[] exportLmkSeedMac() { + return sessionTemplate.withSession("SDFE_ExportLMKSeedMAC", (lib, deviceHandle, sessionHandle) -> { + byte[] mac = new byte[LMK_SEED_MAC_LENGTH]; + sessionTemplate.ensureSuccess("SDFE_ExportLMKSeedMAC", lib.SDFE_ExportLMKSeedMAC(sessionHandle, mac)); + return Arrays.copyOf(mac, mac.length); + }); + } + + @Override + public BackupDataResult backupLmkEx(int outBufferSize) { + int size = requirePositive("outBufferSize", outBufferSize); + + return sessionTemplate.withSession("SDFE_BackupLMK_EX", (lib, deviceHandle, sessionHandle) -> { + SdfeLmkComponent output = new SdfeLmkComponent(); + int structSize = output.size(); + if (size < structSize) { + throw new IllegalArgumentException("outBufferSize must be >= " + structSize); + } + sessionTemplate.ensureSuccess("SDFE_BackupLMK_EX", lib.SDFE_BackupLMK_EX(sessionHandle, output)); + byte[] outputBytes = toBytes(output); + return toBackupResult("SDFE_BackupLMK_EX", outputBytes, outputBytes.length); + }); + } + + @Override + public void recoverLmkEx(byte[] lmkComponent) { + SdfeLmkComponent input = toSdfeLmkComponent("lmkComponent", lmkComponent); + + sessionTemplate.withSession("SDFE_RecoverLMK_EX", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_RecoverLMK_EX", lib.SDFE_RecoverLMK_EX(sessionHandle, input)); + return null; + }); + } + + @Override + public void generateIk(int keyType) { + int safeKeyType = requireNonNegative("keyType", keyType); + + sessionTemplate.withSession("SDFE_GenerateIK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_GenerateIK", lib.SDFE_GenerateIK(sessionHandle, safeKeyType)); + return null; + }); + } + + @Override + public void backupIk(int keyType) { + int safeKeyType = requireNonNegative("keyType", keyType); + + sessionTemplate.withSession("SDFE_BackupIK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_BackupIK", lib.SDFE_BackupIK(sessionHandle, safeKeyType)); + return null; + }); + } + + @Override + public void recoverIk(int keyType) { + int safeKeyType = requireNonNegative("keyType", keyType); + + sessionTemplate.withSession("SDFE_RecoverIK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_RecoverIK", lib.SDFE_RecoverIK(sessionHandle, safeKeyType)); + return null; + }); + } + + @Override + public void destroyIk(int keyType) { + int safeKeyType = requireNonNegative("keyType", keyType); + + sessionTemplate.withSession("SDFE_DestroyIK", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_DestroyIK", lib.SDFE_DestroyIK(sessionHandle, safeKeyType)); + return null; + }); + } + + @Override + public KeyStatusResult statusIk(int keyType) { + int safeKeyType = requireNonNegative("keyType", keyType); + + return sessionTemplate.withSession("SDFE_StatusIK", (lib, deviceHandle, sessionHandle) -> { + IntByReference stateRef = new IntByReference(); + sessionTemplate.ensureSuccess("SDFE_StatusIK", lib.SDFE_StatusIK(sessionHandle, safeKeyType, stateRef)); + return toKeyStatus(stateRef.getValue()); + }); + } + + @Override + public void generateUkey(UkeyGenerateRequest request) { + UkeyGenerateRequest req = requireRequest("request", request); + int adminIndex = requireByteRange("adminIndex", req.getAdminIndex()); + byte[] ukeyPin = requireNonEmptyBytes("ukeyPin", req.getUkeyPin()); + byte[] loginPin = requireNonEmptyBytes("loginPin", req.getLoginPin()); + + sessionTemplate.withSession("SDFE_GenerateUkey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_GenerateUkey", + lib.SDFE_GenerateUkey( + sessionHandle, + (byte) adminIndex, + ukeyPin, + ukeyPin.length, + loginPin, + loginPin.length + ) + ); + return null; + }); + } + + @Override + public void loginUkey(UkeyLoginRequest request) { + UkeyLoginRequest req = requireRequest("request", request); + byte[] ukeyPin = requireNonEmptyBytes("ukeyPin", req.getUkeyPin()); + byte[] loginPin = requireNonEmptyBytes("loginPin", req.getLoginPin()); + + sessionTemplate.withSession("SDFE_LoginUkey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_LoginUkey", + lib.SDFE_LoginUkey(sessionHandle, ukeyPin, ukeyPin.length, loginPin, loginPin.length) + ); + return null; + }); + } + + @Override + public void changeUkeyPin(UkeyPinChangeRequest request) { + UkeyPinChangeRequest req = requireRequest("request", request); + int pinType = requireNonNegative("pinType", req.getPinType()); + byte[] oldPin = requireNonEmptyBytes("oldPin", req.getOldPin()); + byte[] newPin = requireNonEmptyBytes("newPin", req.getNewPin()); + + sessionTemplate.withSession("SDFE_ChangeUkeyPin", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ChangeUkeyPin", + lib.SDFE_ChangeUkeyPin(sessionHandle, pinType, oldPin, oldPin.length, newPin, newPin.length) + ); + return null; + }); + } + + @Override + public void unlockUkey(UkeyUnlockRequest request) { + UkeyUnlockRequest req = requireRequest("request", request); + byte[] adminPin = requireNonEmptyBytes("adminPin", req.getAdminPin()); + byte[] userPin = requireNonEmptyBytes("userPin", req.getUserPin()); + + sessionTemplate.withSession("SDFE_UnlockUkey", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_UnlockUkey", + lib.SDFE_UnlockUkey(sessionHandle, adminPin, adminPin.length, userPin, userPin.length) + ); + return null; + }); + } + + @Override + public void readLmkComponent(byte[] ukeyPin) { + byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin); + + sessionTemplate.withSession("SDFE_ReadLMKComponent", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_ReadLMKComponent", lib.SDFE_ReadLMKComponent(sessionHandle, pin, pin.length)); + return null; + }); + } + + @Override + public void readUkeyIkComponent(int keyType, byte[] ukeyPin) { + int safeKeyType = requireNonNegative("keyType", keyType); + byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin); + + sessionTemplate.withSession("SDFE_ReadUkeyIKComponent", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDFE_ReadUkeyIKComponent", + lib.SDFE_ReadUkeyIKComponent(sessionHandle, safeKeyType, pin, pin.length) + ); + return null; + }); + } + + @Override + public void generateCertificate(byte[] ukeyPin) { + byte[] pin = requireNonEmptyBytes("ukeyPin", ukeyPin); + + sessionTemplate.withSession("SDFE_GenerateCertificate", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_GenerateCertificate", lib.SDFE_GenerateCertificate(sessionHandle, pin, pin.length)); + return null; + }); + } + + @Override + public void logoutAdmin(int adminIndex) { + int safeAdminIndex = requireByteRange("adminIndex", adminIndex); + + sessionTemplate.withSession("SDFE_LoginoutAdmin", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDFE_LoginoutAdmin", lib.SDFE_LoginoutAdmin(sessionHandle, (byte) safeAdminIndex)); + return null; + }); + } + + @Override + public LoginStatusResult loginStatus() { + return sessionTemplate.withSession("SDFE_LoginStatus", (lib, deviceHandle, sessionHandle) -> { + SdfeLoginState state = new SdfeLoginState(); + sessionTemplate.ensureSuccess("SDFE_LoginStatus", lib.SDFE_LoginStatus(sessionHandle, state)); + state.read(); + + LoginStatusResult result = new LoginStatusResult(); + result.setAdmin1(state.admin1); + result.setAdmin2(state.admin2); + result.setAdmin3(state.admin3); + return result; + }); + } + + @Override + public void createFile(FileCreateRequest request) { + FileCreateRequest req = requireRequest("request", request); + byte[] fileName = fileNameBytes(req.getFileName()); + int fileSize = requirePositive("fileSize", req.getFileSize()); + + sessionTemplate.withSession("SDF_CreateFile", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDF_CreateFile", lib.SDF_CreateFile(sessionHandle, fileName, fileName.length, fileSize)); + return null; + }); + } + + @Override + public void writeFile(FileWriteRequest request) { + FileWriteRequest req = requireRequest("request", request); + byte[] fileName = fileNameBytes(req.getFileName()); + int offset = requireNonNegative("offset", req.getOffset()); + byte[] data = requireBytes("data", req.getData()); + + sessionTemplate.withSession("SDF_WriteFile", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess( + "SDF_WriteFile", + lib.SDF_WriteFile(sessionHandle, fileName, fileName.length, offset, data.length, data) + ); + return null; + }); + } + + @Override + public BackupDataResult readFile(FileReadRequest request) { + FileReadRequest req = requireRequest("request", request); + byte[] fileName = fileNameBytes(req.getFileName()); + int offset = requireNonNegative("offset", req.getOffset()); + int readLength = requirePositive("readLength", req.getReadLength()); + + return sessionTemplate.withSession("SDF_ReadFile", (lib, deviceHandle, sessionHandle) -> { + byte[] data = new byte[readLength]; + IntByReference outLen = new IntByReference(readLength); + sessionTemplate.ensureSuccess( + "SDF_ReadFile", + lib.SDF_ReadFile(sessionHandle, fileName, fileName.length, offset, outLen, data) + ); + return toBackupResult("SDF_ReadFile", data, outLen.getValue()); + }); + } + + @Override + public void deleteFile(String fileName) { + byte[] name = fileNameBytes(fileName); + sessionTemplate.withSession("SDF_DeleteFile", (lib, deviceHandle, sessionHandle) -> { + sessionTemplate.ensureSuccess("SDF_DeleteFile", lib.SDF_DeleteFile(sessionHandle, name, name.length)); + return null; + }); + } + + @FunctionalInterface + private interface KeyHandleCallback { + T apply(Pointer keyHandle); + } + + private T withImportedPlainKey( + PcieNativeLibrary lib, + Pointer sessionHandle, + byte[] key, + KeyHandleCallback callback + ) { + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess("SDF_ImportKey", lib.SDF_ImportKey(sessionHandle, key, key.length, keyHandleRef)); + Pointer keyHandle = keyHandleRef.getValue(); + try { + return callback.apply(keyHandle); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandle); + } + } + + private T withImportedKekKey( + PcieNativeLibrary lib, + Pointer sessionHandle, + int algId, + int kekIndex, + byte[] wrappedKey, + KeyHandleCallback callback + ) { + PointerByReference keyHandleRef = new PointerByReference(); + sessionTemplate.ensureSuccess( + "SDF_ImportKeyWithKEK", + lib.SDF_ImportKeyWithKEK(sessionHandle, algId, wrappedKey, wrappedKey.length, kekIndex, keyHandleRef) + ); + Pointer keyHandle = keyHandleRef.getValue(); + try { + return callback.apply(keyHandle); + } finally { + destroyKeyHandle(lib, sessionHandle, keyHandle); + } + } + + private static void destroyKeyHandle( + PcieNativeLibrary lib, + Pointer sessionHandle, + Pointer keyHandle + ) { + if (keyHandle == null) { + return; + } + int destroyCode = lib.SDF_DestroyKey(sessionHandle, keyHandle); + if (destroyCode != 0) { + throw new PcieCryptoException("SDF_DestroyKey", destroyCode, "destroy key failed"); + } + } + + private static byte[] fileNameBytes(String fileName) { + if (fileName == null || fileName.isBlank()) { + throw new IllegalArgumentException("fileName must not be blank"); + } + return fileName.getBytes(StandardCharsets.UTF_8); + } + + private static String zeroTerminatedString(byte[] value) { + int len = 0; + while (len < value.length && value[len] != 0) { + len++; + } + return new String(value, 0, len, StandardCharsets.UTF_8).trim(); + } + + private static StandardKeyPairResult toStandardKeyPairResult(byte[] publicKey, byte[] privateKey) { + StandardKeyPairResult result = new StandardKeyPairResult(); + result.setPublicKey(Arrays.copyOf(publicKey, publicKey.length)); + result.setPublicKeyLength(publicKey.length); + result.setPrivateKey(Arrays.copyOf(privateKey, privateKey.length)); + result.setPrivateKeyLength(privateKey.length); + return result; + } + + private static BackupDataResult toBackupResult(String apiName, byte[] out, int outLen) { + if (outLen < 0 || outLen > out.length) { + throw new PcieCryptoException(apiName, -1, "native returned invalid output length: " + outLen); + } + BackupDataResult result = new BackupDataResult(); + result.setLength(outLen); + result.setData(Arrays.copyOf(out, outLen)); + return result; + } + + private static KeyStatusResult toKeyStatus(int stateCode) { + PcieKeyState state = PcieKeyState.from(stateCode); + KeyStatusResult result = new KeyStatusResult(); + result.setKeyState(stateCode); + result.setKeyStateName(state.name()); + return result; + } + + private static int requireUserKeyType(int keyType) { + if (keyType != PcieUserKeyType.SIGN.getCode() && keyType != PcieUserKeyType.ENC.getCode()) { + throw new IllegalArgumentException("keyType must be 0(SIGN) or 1(ENC)"); + } + return keyType; + } + + private static int requirePositive(String name, int value) { + if (value <= 0) { + throw new IllegalArgumentException(name + " must be > 0"); + } + return value; + } + + private static int requireNonNegative(String name, int value) { + if (value < 0) { + throw new IllegalArgumentException(name + " must be >= 0"); + } + return value; + } + + private static int requireByteRange(String name, int value) { + if (value < 0 || value > 255) { + throw new IllegalArgumentException(name + " must be in [0,255]"); + } + return value; + } + + private static byte[] requireNonEmptyBytes(String name, byte[] value) { + if (value == null || value.length == 0) { + throw new IllegalArgumentException(name + " must not be empty"); + } + return value; + } + + private static byte[] requireBytes(String name, byte[] value) { + if (value == null) { + throw new IllegalArgumentException(name + " must not be null"); + } + return value; + } + + private static RsaRefPublicKey toRsaRefPublicKey(String name, byte[] value) { + return toStructure(name, value, new RsaRefPublicKey(), false); + } + + private static RsaRefPrivateKey toRsaRefPrivateKey(String name, byte[] value) { + return toStructure(name, value, new RsaRefPrivateKey(), false); + } + + private static EccRefPublicKey toEccRefPublicKey(String name, byte[] value) { + return toStructure(name, value, new EccRefPublicKey(), false); + } + + private static EccRefPrivateKey toEccRefPrivateKey(String name, byte[] value) { + return toStructure(name, value, new EccRefPrivateKey(), false); + } + + private static EccSignature toEccSignature(String name, byte[] value) { + return toStructure(name, value, new EccSignature(), false); + } + + private static EccCipher toEccCipher(String name, byte[] value) { + return toStructure(name, value, new EccCipher(), true); + } + + private static SdfeKekComponent toSdfeKekComponent(String name, byte[] value) { + return toStructure(name, value, new SdfeKekComponent(), false); + } + + private static SdfeLmkComponent toSdfeLmkComponent(String name, byte[] value) { + return toStructure(name, value, new SdfeLmkComponent(), false); + } + + private static EnvelopedKeyBlob toEnvelopedKeyBlob(String name, byte[] value) { + return toStructure(name, value, new EnvelopedKeyBlob(), true); + } + + private static byte[] toBytes(Structure structure) { + structure.read(); + return structure.getPointer().getByteArray(0, structure.size()); + } + + private static byte[] toEccCipherBytes(String apiName, EccCipher cipher) { + cipher.read(); + int cLength = cipher.l; + if (cLength < 0 || cLength > EccCipher.C_MAX_LEN) { + throw new PcieCryptoException(apiName, -1, "native returned invalid ECC cipher C length: " + cLength); + } + int totalLength = ECC_CIPHER_PREFIX_LENGTH + cLength; + if (totalLength < 0 || totalLength > cipher.size()) { + throw new PcieCryptoException(apiName, -1, "native returned invalid ECC cipher blob length: " + totalLength); + } + return cipher.getPointer().getByteArray(0, totalLength); + } + + private static T toStructure(String name, byte[] value, T structure, boolean allowPartial) { + byte[] source = requireNonEmptyBytes(name, value); + int size = structure.size(); + if (allowPartial) { + if (source.length > size) { + throw new IllegalArgumentException(name + " length must be <= " + size + ", actual: " + source.length); + } + } else if (source.length != size) { + throw new IllegalArgumentException(name + " length must be exactly " + size + ", actual: " + source.length); + } + Pointer pointer = structure.getPointer(); + pointer.clear(size); + pointer.write(0, source, 0, source.length); + structure.read(); + return structure; + } + + private static T requireRequest(String name, T request) { + if (request == null) { + throw new IllegalArgumentException(name + " must not be null"); + } + return request; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/MockPcieCryptoService.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/MockPcieCryptoService.java new file mode 100644 index 0000000..df96808 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/MockPcieCryptoService.java @@ -0,0 +1,896 @@ +package com.cisd.tms.integration.crypto.pcie.service; + +import com.cisd.tms.integration.crypto.pcie.PcieKeyState; +import com.cisd.tms.integration.crypto.pcie.PcieUserKeyType; +import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult; +import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult; +import com.cisd.tms.integration.crypto.pcie.model.ChangePrivateKeyPasswordRequest; +import com.cisd.tms.integration.crypto.pcie.model.DeviceConfResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceCountResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceInfoResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.DigestRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalDecryptRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalEncryptRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalVerifyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccInternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccInternalVerifyRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExportKekComponentRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileCreateRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileReadRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileWriteRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateAgreementDataAndKeyEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardEccKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardRsaKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacResult; +import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.KekComponentRequest; +import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.LoginStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest; +import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest; +import com.cisd.tms.integration.crypto.pcie.model.RecoverKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPrivateKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPublicKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaInternalKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult; +import com.cisd.tms.integration.crypto.pcie.model.UkeyGenerateRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyLoginRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyPinChangeRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyUnlockRequest; +import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest; +import java.util.Arrays; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +public class MockPcieCryptoService implements PcieCryptoService { + + private static final int ECC_KEY_BITS = 256; + + @Override + public DeviceCountResult getDeviceCount() { + DeviceCountResult result = new DeviceCountResult(); + result.setDeviceNumber(0); + result.setNormalDeviceNumber(0); + return result; + } + + @Override + public DeviceConfResult getDeviceConf() { + return new DeviceConfResult(); + } + + @Override + public DeviceInfoResult getDeviceInfo() { + return new DeviceInfoResult(); + } + + @Override + public byte[] generateRandom(int length) { + int randomLength = requirePositive("length", length); + byte[] output = new byte[randomLength]; + Arrays.fill(output, (byte) 0x6A); + return output; + } + + @Override + public void initIdentify(byte[] oldPin, byte[] newPin) { + requireNonEmptyBytes("oldPin", oldPin); + requireNonEmptyBytes("newPin", newPin); + } + + @Override + public void deviceSelfTest() { + // no-op + } + + @Override + public DeviceStatusResult getDeviceStatus(int statusBufferSize) { + int size = requirePositive("statusBufferSize", statusBufferSize); + DeviceStatusResult result = new DeviceStatusResult(); + result.setLength(size); + result.setStatusData(new byte[size]); + return result; + } + + @Override + public void deviceFactoryReset() { + // no-op + } + + @Override + public void changePrivateKeyAccessPassword(ChangePrivateKeyPasswordRequest request) { + ChangePrivateKeyPasswordRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireNonEmptyBytes("oldPassword", req.getOldPassword()); + requireNonEmptyBytes("newPassword", req.getNewPassword()); + } + + @Override + public void getPrivateKeyAccessRight(PrivateKeyAccessRequest request) { + PrivateKeyAccessRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireNonEmptyBytes("password", req.getPassword()); + } + + @Override + public void releasePrivateKeyAccessRight(int keyIndex) { + requireNonNegative("keyIndex", keyIndex); + } + + @Override + public void generateKeyPairEcc(GenerateKeyPairRequest request) { + GenerateKeyPairRequest req = requireRequest("request", request); + if (req.getKeyBits() != ECC_KEY_BITS) { + throw new IllegalArgumentException("keyBits must be 256 for ECC"); + } + requireNonNegative("keyIndex", req.getKeyIndex()); + requireUserKeyType(req.getKeyType()); + } + + @Override + public void generateKeyPairRsa(GenerateKeyPairRequest request) { + GenerateKeyPairRequest req = requireRequest("request", request); + requirePositive("keyBits", req.getKeyBits()); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireUserKeyType(req.getKeyType()); + } + + @Override + public void importKeyPairEcc(ImportKeyPairRequest request) { + validateImportKeyPair(request); + } + + @Override + public void importKeyPairRsa(ImportKeyPairRequest request) { + validateImportKeyPair(request); + } + + @Override + public void generateKek(GenerateKekRequest request) { + GenerateKekRequest req = requireRequest("request", request); + int keyBits = req.getKeyBits(); + if (keyBits != 128 && keyBits != 192 && keyBits != 256) { + throw new IllegalArgumentException("keyBits must be one of 128/192/256 for KEK"); + } + requireNonNegative("keyIndex", req.getKeyIndex()); + } + + @Override + public void importKek(ImportKekRequest request) { + ImportKekRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireNonEmptyBytes("keyData", req.getKeyData()); + } + + @Override + public void importKekComponent(KekComponentRequest request) { + KekComponentRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requirePositive("componentNum", req.getComponentNum()); + requireNonEmptyBytes("componentData", req.getComponentData()); + } + + @Override + public BackupDataResult exportKekComponent(ExportKekComponentRequest request) { + ExportKekComponentRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requirePositive("componentNum", req.getComponentNum()); + int size = requirePositive("componentSize", req.getComponentSize()); + return mockBackup(size, req.getComponentNum()); + } + + @Override + public BackupDataResult backupUserKey(int keyIndex, int keyType, int outBufferSize) { + requireNonNegative("keyIndex", keyIndex); + requireUserKeyType(keyType); + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, keyIndex); + } + + @Override + public void recoverUserKey(RecoverUserKeyRequest request) { + RecoverUserKeyRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireUserKeyType(req.getKeyType()); + requireNonEmptyBytes("encryptedKey", req.getEncryptedKey()); + int storeFlag = req.getStoreFlag(); + if (storeFlag != 0 && storeFlag != 1) { + throw new IllegalArgumentException("storeFlag must be 0 or 1"); + } + } + + @Override + public BackupDataResult backupKek(int keyIndex, int outBufferSize) { + requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, keyIndex); + } + + @Override + public void recoverKek(RecoverKekRequest request) { + RecoverKekRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireNonEmptyBytes("encryptedKey", req.getEncryptedKey()); + } + + @Override + public void deleteUserKey(int keyIndex) { + requireNonNegative("keyIndex", keyIndex); + } + + @Override + public void deleteKek(int keyIndex) { + requireNonNegative("keyIndex", keyIndex); + } + + @Override + public BackupDataResult backupAllKey(int outBufferSize) { + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, 0x5A); + } + + @Override + public void restoreAllKey(byte[] keyImage) { + requireNonEmptyBytes("keyImage", keyImage); + } + + @Override + public KeyStatusResult statusUserKeyEcc(int keyIndex, int keyType) { + requireNonNegative("keyIndex", keyIndex); + requireUserKeyType(keyType); + return keyStatus(PcieKeyState.RIGHT); + } + + @Override + public KeyStatusResult statusUserKeyRsa(int keyIndex, int keyType) { + requireNonNegative("keyIndex", keyIndex); + requireUserKeyType(keyType); + return keyStatus(PcieKeyState.RIGHT); + } + + @Override + public KeyStatusResult statusKek(int keyIndex) { + requireNonNegative("keyIndex", keyIndex); + return keyStatus(PcieKeyState.RIGHT); + } + + @Override + public void importEncryptedKeyPairEcc(ImportEncKeyPairEccRequest request) { + ImportEncKeyPairEccRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireNonEmptyBytes("envelopedKeyBlob", req.getEnvelopedKeyBlob()); + } + + @Override + public void importEncryptedKeyPairRsa(ImportEncKeyPairRsaRequest request) { + ImportEncKeyPairRsaRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requirePositive("symAlgId", req.getSymAlgId()); + requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + requireNonEmptyBytes("encryptedData", req.getEncryptedData()); + } + + @Override + public BackupDataResult updateBackedKey(UpdateBackedKeyRequest request) { + UpdateBackedKeyRequest req = requireRequest("request", request); + requireNonEmptyBytes("oldData", req.getOldData()); + int size = requirePositive("newDataBufferSize", req.getNewDataBufferSize()); + return mockBackup(size, 0x33); + } + + @Override + public BackupDataResult exportSignPublicKeyRsa(int keyIndex, int outBufferSize) { + requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, 0x41); + } + + @Override + public BackupDataResult exportEncPublicKeyRsa(int keyIndex, int outBufferSize) { + requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, 0x42); + } + + @Override + public BackupDataResult exportSignPublicKeyEcc(int keyIndex, int outBufferSize) { + requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, 0x43); + } + + @Override + public BackupDataResult exportEncPublicKeyEcc(int keyIndex, int outBufferSize) { + requireNonNegative("keyIndex", keyIndex); + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, 0x44); + } + + @Override + public StandardKeyPairResult generateStandardRsaKeyPair(GenerateStandardRsaKeyPairRequest request) { + GenerateStandardRsaKeyPairRequest req = requireRequest("request", request); + requirePositive("keyBits", req.getKeyBits()); + int pubSize = requirePositive("publicKeyBufferSize", req.getPublicKeyBufferSize()); + int priSize = requirePositive("privateKeyBufferSize", req.getPrivateKeyBufferSize()); + return mockStandardKeyPair(pubSize, priSize, 0x53, 0x54); + } + + @Override + public StandardKeyPairResult generateStandardEccKeyPair(GenerateStandardEccKeyPairRequest request) { + GenerateStandardEccKeyPairRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requirePositive("keyBits", req.getKeyBits()); + int pubSize = requirePositive("publicKeyBufferSize", req.getPublicKeyBufferSize()); + int priSize = requirePositive("privateKeyBufferSize", req.getPrivateKeyBufferSize()); + return mockStandardKeyPair(pubSize, priSize, 0x55, 0x56); + } + + @Override + public BackupDataResult generateKeyWithKek(GenerateKeyWithKekRequest request) { + GenerateKeyWithKekRequest req = requireRequest("request", request); + requirePositive("keyBits", req.getKeyBits()); + requirePositive("algId", req.getAlgId()); + requireNonNegative("kekIndex", req.getKekIndex()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x45); + } + + @Override + public BackupDataResult rsaExternalPublicKeyOperation(RsaExternalPublicKeyOpRequest request) { + RsaExternalPublicKeyOpRequest req = requireRequest("request", request); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + requireBytes("input", req.getInput()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x46); + } + + @Override + public BackupDataResult rsaExternalPrivateKeyOperation(RsaExternalPrivateKeyOpRequest request) { + RsaExternalPrivateKeyOpRequest req = requireRequest("request", request); + requireNonEmptyBytes("privateKeyBlob", req.getPrivateKeyBlob()); + requireBytes("input", req.getInput()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x4C); + } + + @Override + public BackupDataResult rsaInternalPublicKeyOperation(RsaInternalKeyOpRequest request) { + RsaInternalKeyOpRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireBytes("input", req.getInput()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x47); + } + + @Override + public BackupDataResult rsaInternalPrivateKeyOperation(RsaInternalKeyOpRequest request) { + RsaInternalKeyOpRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireBytes("input", req.getInput()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x48); + } + + @Override + public BackupDataResult generateKeyWithIpkRsa(GenerateKeyWithIpkRsaRequest request) { + GenerateKeyWithIpkRsaRequest req = requireRequest("request", request); + requireNonNegative("ipkIndex", req.getIpkIndex()); + requirePositive("keyBits", req.getKeyBits()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x4D); + } + + @Override + public BackupDataResult generateKeyWithEpkRsa(GenerateKeyWithEpkRsaRequest request) { + GenerateKeyWithEpkRsaRequest req = requireRequest("request", request); + requirePositive("keyBits", req.getKeyBits()); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x4E); + } + + @Override + public void importKeyWithIskRsa(ImportKeyWithIskRsaRequest request) { + ImportKeyWithIskRsaRequest req = requireRequest("request", request); + requireNonNegative("iskIndex", req.getIskIndex()); + requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + } + + @Override + public BackupDataResult generateKeyWithIpkEcc(GenerateKeyWithIpkEccRequest request) { + GenerateKeyWithIpkEccRequest req = requireRequest("request", request); + requireNonNegative("ipkIndex", req.getIpkIndex()); + requirePositive("keyBits", req.getKeyBits()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x50); + } + + @Override + public BackupDataResult generateKeyWithEpkEcc(GenerateKeyWithEpkEccRequest request) { + GenerateKeyWithEpkEccRequest req = requireRequest("request", request); + requirePositive("keyBits", req.getKeyBits()); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x51); + } + + @Override + public void importKeyWithIskEcc(ImportKeyWithIskEccRequest request) { + ImportKeyWithIskEccRequest req = requireRequest("request", request); + requireNonNegative("iskIndex", req.getIskIndex()); + requireNonEmptyBytes("encryptedKeyBlob", req.getEncryptedKeyBlob()); + } + + @Override + public BackupDataResult exchangeDigitEnvelopeBaseOnRsa(ExchangeDigitEnvelopeRsaRequest request) { + ExchangeDigitEnvelopeRsaRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + requireNonEmptyBytes("inputEnvelopeBlob", req.getInputEnvelopeBlob()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x52); + } + + @Override + public BackupDataResult exchangeDigitEnvelopeBaseOnEcc(ExchangeDigitEnvelopeEccRequest request) { + ExchangeDigitEnvelopeEccRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + requireNonEmptyBytes("inputEnvelopeBlob", req.getInputEnvelopeBlob()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x57); + } + + @Override + public AgreementDataAndKeyEccResult generateAgreementDataAndKeyWithEcc(GenerateAgreementDataAndKeyEccRequest request) { + GenerateAgreementDataAndKeyEccRequest req = requireRequest("request", request); + requireNonNegative("iskIndex", req.getIskIndex()); + requirePositive("keyBits", req.getKeyBits()); + requireNonEmptyBytes("responseId", req.getResponseId()); + requireNonEmptyBytes("sponsorId", req.getSponsorId()); + requireNonEmptyBytes("sponsorPublicKeyBlob", req.getSponsorPublicKeyBlob()); + requireNonEmptyBytes("sponsorTmpPublicKeyBlob", req.getSponsorTmpPublicKeyBlob()); + int responsePublicKeySize = requirePositive("responsePublicKeyBufferSize", req.getResponsePublicKeyBufferSize()); + int responseTmpPublicKeySize = requirePositive("responseTmpPublicKeyBufferSize", req.getResponseTmpPublicKeyBufferSize()); + + BackupDataResult responsePublicKey = mockBackup(responsePublicKeySize, 0x58); + BackupDataResult responseTmpPublicKey = mockBackup(responseTmpPublicKeySize, 0x59); + + AgreementDataAndKeyEccResult result = new AgreementDataAndKeyEccResult(); + result.setResponsePublicKey(responsePublicKey.getData()); + result.setResponsePublicKeyLength(responsePublicKey.getLength()); + result.setResponseTmpPublicKey(responseTmpPublicKey.getData()); + result.setResponseTmpPublicKeyLength(responseTmpPublicKey.getLength()); + result.setSessionKeyGenerated(true); + return result; + } + + @Override + public EccAgreementSessionKeyResult generateSessionKeyWithEccAgreement(EccAgreementSessionKeyRequest request) { + EccAgreementSessionKeyRequest req = requireRequest("request", request); + requireNonNegative("iskIndex", req.getIskIndex()); + requirePositive("keyBits", req.getKeyBits()); + requireNonEmptyBytes("sponsorId", req.getSponsorId()); + requireNonEmptyBytes("responseId", req.getResponseId()); + requireNonEmptyBytes("responsePublicKeyBlob", req.getResponsePublicKeyBlob()); + requireNonEmptyBytes("responseTmpPublicKeyBlob", req.getResponseTmpPublicKeyBlob()); + int sponsorPublicKeySize = requirePositive("sponsorPublicKeyBufferSize", req.getSponsorPublicKeyBufferSize()); + int sponsorTmpPublicKeySize = requirePositive("sponsorTmpPublicKeyBufferSize", req.getSponsorTmpPublicKeyBufferSize()); + int sessionKeySize = requirePositive("sessionKeyBufferSize", req.getSessionKeyBufferSize()); + + BackupDataResult sponsorPublicKey = mockBackup(sponsorPublicKeySize, 0x5A); + BackupDataResult sponsorTmpPublicKey = mockBackup(sponsorTmpPublicKeySize, 0x5B); + BackupDataResult sessionKey = mockBackup(sessionKeySize, 0x5C); + + EccAgreementSessionKeyResult result = new EccAgreementSessionKeyResult(); + result.setSponsorPublicKey(sponsorPublicKey.getData()); + result.setSponsorPublicKeyLength(sponsorPublicKey.getLength()); + result.setSponsorTmpPublicKey(sponsorTmpPublicKey.getData()); + result.setSponsorTmpPublicKeyLength(sponsorTmpPublicKey.getLength()); + result.setSessionKey(sessionKey.getData()); + result.setSessionKeyLength(sessionKey.getLength()); + result.setSessionKeyGenerated(true); + return result; + } + + @Override + public BackupDataResult eccInternalSign(EccInternalSignRequest request) { + EccInternalSignRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireBytes("data", req.getData()); + int size = requirePositive("signatureBufferSize", req.getSignatureBufferSize()); + return mockBackup(size, 0x49); + } + + @Override + public BackupDataResult eccExternalSign(EccExternalSignRequest request) { + EccExternalSignRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("privateKeyBlob", req.getPrivateKeyBlob()); + requireBytes("data", req.getData()); + int size = requirePositive("signatureBufferSize", req.getSignatureBufferSize()); + return mockBackup(size, 0x4F); + } + + @Override + public void eccInternalVerify(EccInternalVerifyRequest request) { + EccInternalVerifyRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireBytes("data", req.getData()); + requireNonEmptyBytes("signature", req.getSignature()); + } + + @Override + public void eccExternalVerify(EccExternalVerifyRequest request) { + EccExternalVerifyRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + requireBytes("data", req.getData()); + requireNonEmptyBytes("signature", req.getSignature()); + } + + @Override + public BackupDataResult eccExternalEncrypt(EccExternalEncryptRequest request) { + EccExternalEncryptRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("publicKeyBlob", req.getPublicKeyBlob()); + requireBytes("data", req.getData()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x4A); + } + + @Override + public BackupDataResult eccExternalDecrypt(EccExternalDecryptRequest request) { + EccExternalDecryptRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("privateKeyBlob", req.getPrivateKeyBlob()); + requireNonEmptyBytes("encryptedData", req.getEncryptedData()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x4B); + } + + @Override + public BackupDataResult encryptWithPlainKey(SymmetricCryptoRequest request) { + SymmetricCryptoRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("key", req.getKey()); + byte[] data = requireBytes("data", req.getData()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, data.length); + } + + @Override + public BackupDataResult decryptWithPlainKey(SymmetricCryptoRequest request) { + return encryptWithPlainKey(request); + } + + @Override + public BackupDataResult encryptWithKekWrappedKey(SymmetricKekCryptoRequest request) { + SymmetricKekCryptoRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonNegative("kekIndex", req.getKekIndex()); + requireNonEmptyBytes("wrappedKey", req.getWrappedKey()); + byte[] data = requireBytes("data", req.getData()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, data.length + req.getKekIndex()); + } + + @Override + public BackupDataResult decryptWithKekWrappedKey(SymmetricKekCryptoRequest request) { + return encryptWithKekWrappedKey(request); + } + + @Override + public BackupDataResult calculateMacWithPlainKey(MacCalcRequest request) { + MacCalcRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireNonEmptyBytes("key", req.getKey()); + requireBytes("data", req.getData()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x55); + } + + @Override + public BackupDataResult digest(DigestRequest request) { + DigestRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + requireBytes("data", req.getData()); + int size = requirePositive("outBufferSize", req.getOutBufferSize()); + return mockBackup(size, 0x77); + } + + @Override + public HmacResult hmac(HmacRequest request) { + HmacRequest req = requireRequest("request", request); + requirePositive("algId", req.getAlgId()); + byte[] key = requireNonEmptyBytes("key", req.getKey()); + byte[] data = requireBytes("data", req.getData()); + + try { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(key, "HmacSHA256")); + byte[] hmac = mac.doFinal(data); + HmacResult result = new HmacResult(); + result.setHmac(hmac); + result.setHmacLength(hmac.length); + return result; + } catch (Exception ex) { + throw new IllegalStateException("mock hmac failed", ex); + } + } + + @Override + public void generateLmk() { + // no-op + } + + @Override + public void loadLmk() { + // no-op + } + + @Override + public void backupLmk() { + // no-op + } + + @Override + public void recoverLmk() { + // no-op + } + + @Override + public void destroyLmk() { + // no-op + } + + @Override + public void checkLmk() { + // no-op + } + + @Override + public byte[] exportLmkSeedMac() { + return new byte[8]; + } + + @Override + public BackupDataResult backupLmkEx(int outBufferSize) { + int size = requirePositive("outBufferSize", outBufferSize); + return mockBackup(size, 0x11); + } + + @Override + public void recoverLmkEx(byte[] lmkComponent) { + requireNonEmptyBytes("lmkComponent", lmkComponent); + } + + @Override + public void generateIk(int keyType) { + requireNonNegative("keyType", keyType); + } + + @Override + public void backupIk(int keyType) { + requireNonNegative("keyType", keyType); + } + + @Override + public void recoverIk(int keyType) { + requireNonNegative("keyType", keyType); + } + + @Override + public void destroyIk(int keyType) { + requireNonNegative("keyType", keyType); + } + + @Override + public KeyStatusResult statusIk(int keyType) { + requireNonNegative("keyType", keyType); + return keyStatus(PcieKeyState.RIGHT); + } + + @Override + public void generateUkey(UkeyGenerateRequest request) { + UkeyGenerateRequest req = requireRequest("request", request); + requireByteRange("adminIndex", req.getAdminIndex()); + requireNonEmptyBytes("ukeyPin", req.getUkeyPin()); + requireNonEmptyBytes("loginPin", req.getLoginPin()); + } + + @Override + public void loginUkey(UkeyLoginRequest request) { + UkeyLoginRequest req = requireRequest("request", request); + requireNonEmptyBytes("ukeyPin", req.getUkeyPin()); + requireNonEmptyBytes("loginPin", req.getLoginPin()); + } + + @Override + public void changeUkeyPin(UkeyPinChangeRequest request) { + UkeyPinChangeRequest req = requireRequest("request", request); + requireNonNegative("pinType", req.getPinType()); + requireNonEmptyBytes("oldPin", req.getOldPin()); + requireNonEmptyBytes("newPin", req.getNewPin()); + } + + @Override + public void unlockUkey(UkeyUnlockRequest request) { + UkeyUnlockRequest req = requireRequest("request", request); + requireNonEmptyBytes("adminPin", req.getAdminPin()); + requireNonEmptyBytes("userPin", req.getUserPin()); + } + + @Override + public void readLmkComponent(byte[] ukeyPin) { + requireNonEmptyBytes("ukeyPin", ukeyPin); + } + + @Override + public void readUkeyIkComponent(int keyType, byte[] ukeyPin) { + requireNonNegative("keyType", keyType); + requireNonEmptyBytes("ukeyPin", ukeyPin); + } + + @Override + public void generateCertificate(byte[] ukeyPin) { + requireNonEmptyBytes("ukeyPin", ukeyPin); + } + + @Override + public void logoutAdmin(int adminIndex) { + requireByteRange("adminIndex", adminIndex); + } + + @Override + public LoginStatusResult loginStatus() { + return new LoginStatusResult(); + } + + @Override + public void createFile(FileCreateRequest request) { + FileCreateRequest req = requireRequest("request", request); + requireNonBlank("fileName", req.getFileName()); + requirePositive("fileSize", req.getFileSize()); + } + + @Override + public void writeFile(FileWriteRequest request) { + FileWriteRequest req = requireRequest("request", request); + requireNonBlank("fileName", req.getFileName()); + requireNonNegative("offset", req.getOffset()); + requireBytes("data", req.getData()); + } + + @Override + public BackupDataResult readFile(FileReadRequest request) { + FileReadRequest req = requireRequest("request", request); + requireNonBlank("fileName", req.getFileName()); + requireNonNegative("offset", req.getOffset()); + int size = requirePositive("readLength", req.getReadLength()); + return mockBackup(size, req.getOffset()); + } + + @Override + public void deleteFile(String fileName) { + requireNonBlank("fileName", fileName); + } + + private static void validateImportKeyPair(ImportKeyPairRequest request) { + ImportKeyPairRequest req = requireRequest("request", request); + requireNonNegative("keyIndex", req.getKeyIndex()); + requireUserKeyType(req.getKeyType()); + requireNonEmptyBytes("publicKey", req.getPublicKey()); + requireNonEmptyBytes("privateKey", req.getPrivateKey()); + } + + private static KeyStatusResult keyStatus(PcieKeyState state) { + KeyStatusResult result = new KeyStatusResult(); + result.setKeyState(state.getCode()); + result.setKeyStateName(state.name()); + return result; + } + + private static StandardKeyPairResult mockStandardKeyPair(int publicKeySize, int privateKeySize, int publicSeed, int privateSeed) { + BackupDataResult publicPart = mockBackup(publicKeySize, publicSeed); + BackupDataResult privatePart = mockBackup(privateKeySize, privateSeed); + + StandardKeyPairResult result = new StandardKeyPairResult(); + result.setPublicKey(publicPart.getData()); + result.setPublicKeyLength(publicPart.getLength()); + result.setPrivateKey(privatePart.getData()); + result.setPrivateKeyLength(privatePart.getLength()); + return result; + } + + private static BackupDataResult mockBackup(int outBufferSize, int seed) { + int length = Math.min(outBufferSize, 32); + byte[] data = new byte[length]; + Arrays.fill(data, (byte) (seed & 0xFF)); + + BackupDataResult result = new BackupDataResult(); + result.setData(data); + result.setLength(length); + return result; + } + + private static int requireUserKeyType(int keyType) { + if (keyType != PcieUserKeyType.SIGN.getCode() && keyType != PcieUserKeyType.ENC.getCode()) { + throw new IllegalArgumentException("keyType must be 0(SIGN) or 1(ENC)"); + } + return keyType; + } + + private static int requirePositive(String name, int value) { + if (value <= 0) { + throw new IllegalArgumentException(name + " must be > 0"); + } + return value; + } + + private static int requireNonNegative(String name, int value) { + if (value < 0) { + throw new IllegalArgumentException(name + " must be >= 0"); + } + return value; + } + + private static int requireByteRange(String name, int value) { + if (value < 0 || value > 255) { + throw new IllegalArgumentException(name + " must be in [0,255]"); + } + return value; + } + + private static byte[] requireNonEmptyBytes(String name, byte[] value) { + if (value == null || value.length == 0) { + throw new IllegalArgumentException(name + " must not be empty"); + } + return value; + } + + private static byte[] requireBytes(String name, byte[] value) { + if (value == null) { + throw new IllegalArgumentException(name + " must not be null"); + } + return value; + } + + private static String requireNonBlank(String name, String value) { + if (value == null || value.isBlank()) { + throw new IllegalArgumentException(name + " must not be blank"); + } + return value; + } + + private static T requireRequest(String name, T request) { + if (request == null) { + throw new IllegalArgumentException(name + " must not be null"); + } + return request; + } +} diff --git a/src/main/java/com/cisd/tms/integration/crypto/pcie/service/PcieCryptoService.java b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/PcieCryptoService.java new file mode 100644 index 0000000..84d53f1 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/crypto/pcie/service/PcieCryptoService.java @@ -0,0 +1,251 @@ +package com.cisd.tms.integration.crypto.pcie.service; + +import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult; +import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult; +import com.cisd.tms.integration.crypto.pcie.model.ChangePrivateKeyPasswordRequest; +import com.cisd.tms.integration.crypto.pcie.model.DeviceConfResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceCountResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceInfoResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.DigestRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalDecryptRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalEncryptRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalVerifyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccInternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccInternalVerifyRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExportKekComponentRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileCreateRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileReadRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileWriteRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateAgreementDataAndKeyEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardEccKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardRsaKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacResult; +import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportEncKeyPairRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.KekComponentRequest; +import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.LoginStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest; +import com.cisd.tms.integration.crypto.pcie.model.PrivateKeyAccessRequest; +import com.cisd.tms.integration.crypto.pcie.model.RecoverKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.RecoverUserKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPrivateKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPublicKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaInternalKeyOpRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult; +import com.cisd.tms.integration.crypto.pcie.model.UkeyGenerateRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyLoginRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyPinChangeRequest; +import com.cisd.tms.integration.crypto.pcie.model.UkeyUnlockRequest; +import com.cisd.tms.integration.crypto.pcie.model.UpdateBackedKeyRequest; + +public interface PcieCryptoService { + + DeviceCountResult getDeviceCount(); + + DeviceConfResult getDeviceConf(); + + DeviceInfoResult getDeviceInfo(); + + byte[] generateRandom(int length); + + void initIdentify(byte[] oldPin, byte[] newPin); + + void deviceSelfTest(); + + DeviceStatusResult getDeviceStatus(int statusBufferSize); + + void deviceFactoryReset(); + + void changePrivateKeyAccessPassword(ChangePrivateKeyPasswordRequest request); + + void getPrivateKeyAccessRight(PrivateKeyAccessRequest request); + + void releasePrivateKeyAccessRight(int keyIndex); + + void generateKeyPairEcc(GenerateKeyPairRequest request); + + void generateKeyPairRsa(GenerateKeyPairRequest request); + + void importKeyPairEcc(ImportKeyPairRequest request); + + void importKeyPairRsa(ImportKeyPairRequest request); + + void generateKek(GenerateKekRequest request); + + void importKek(ImportKekRequest request); + + void importKekComponent(KekComponentRequest request); + + BackupDataResult exportKekComponent(ExportKekComponentRequest request); + + BackupDataResult backupUserKey(int keyIndex, int keyType, int outBufferSize); + + void recoverUserKey(RecoverUserKeyRequest request); + + BackupDataResult backupKek(int keyIndex, int outBufferSize); + + void recoverKek(RecoverKekRequest request); + + void deleteUserKey(int keyIndex); + + void deleteKek(int keyIndex); + + BackupDataResult backupAllKey(int outBufferSize); + + void restoreAllKey(byte[] keyImage); + + KeyStatusResult statusUserKeyEcc(int keyIndex, int keyType); + + KeyStatusResult statusUserKeyRsa(int keyIndex, int keyType); + + KeyStatusResult statusKek(int keyIndex); + + void importEncryptedKeyPairEcc(ImportEncKeyPairEccRequest request); + + void importEncryptedKeyPairRsa(ImportEncKeyPairRsaRequest request); + + BackupDataResult updateBackedKey(UpdateBackedKeyRequest request); + + BackupDataResult exportSignPublicKeyRsa(int keyIndex, int outBufferSize); + + BackupDataResult exportEncPublicKeyRsa(int keyIndex, int outBufferSize); + + BackupDataResult exportSignPublicKeyEcc(int keyIndex, int outBufferSize); + + BackupDataResult exportEncPublicKeyEcc(int keyIndex, int outBufferSize); + + StandardKeyPairResult generateStandardRsaKeyPair(GenerateStandardRsaKeyPairRequest request); + + StandardKeyPairResult generateStandardEccKeyPair(GenerateStandardEccKeyPairRequest request); + + BackupDataResult generateKeyWithKek(GenerateKeyWithKekRequest request); + + BackupDataResult rsaExternalPublicKeyOperation(RsaExternalPublicKeyOpRequest request); + + BackupDataResult rsaExternalPrivateKeyOperation(RsaExternalPrivateKeyOpRequest request); + + BackupDataResult rsaInternalPublicKeyOperation(RsaInternalKeyOpRequest request); + + BackupDataResult rsaInternalPrivateKeyOperation(RsaInternalKeyOpRequest request); + + BackupDataResult generateKeyWithIpkRsa(GenerateKeyWithIpkRsaRequest request); + + BackupDataResult generateKeyWithEpkRsa(GenerateKeyWithEpkRsaRequest request); + + void importKeyWithIskRsa(ImportKeyWithIskRsaRequest request); + + BackupDataResult generateKeyWithIpkEcc(GenerateKeyWithIpkEccRequest request); + + BackupDataResult generateKeyWithEpkEcc(GenerateKeyWithEpkEccRequest request); + + void importKeyWithIskEcc(ImportKeyWithIskEccRequest request); + + BackupDataResult exchangeDigitEnvelopeBaseOnRsa(ExchangeDigitEnvelopeRsaRequest request); + + BackupDataResult exchangeDigitEnvelopeBaseOnEcc(ExchangeDigitEnvelopeEccRequest request); + + AgreementDataAndKeyEccResult generateAgreementDataAndKeyWithEcc(GenerateAgreementDataAndKeyEccRequest request); + + EccAgreementSessionKeyResult generateSessionKeyWithEccAgreement(EccAgreementSessionKeyRequest request); + + BackupDataResult eccInternalSign(EccInternalSignRequest request); + + BackupDataResult eccExternalSign(EccExternalSignRequest request); + + void eccInternalVerify(EccInternalVerifyRequest request); + + void eccExternalVerify(EccExternalVerifyRequest request); + + BackupDataResult eccExternalEncrypt(EccExternalEncryptRequest request); + + BackupDataResult eccExternalDecrypt(EccExternalDecryptRequest request); + + BackupDataResult encryptWithPlainKey(SymmetricCryptoRequest request); + + BackupDataResult decryptWithPlainKey(SymmetricCryptoRequest request); + + BackupDataResult encryptWithKekWrappedKey(SymmetricKekCryptoRequest request); + + BackupDataResult decryptWithKekWrappedKey(SymmetricKekCryptoRequest request); + + BackupDataResult calculateMacWithPlainKey(MacCalcRequest request); + + BackupDataResult digest(DigestRequest request); + + HmacResult hmac(HmacRequest request); + + void generateLmk(); + + void loadLmk(); + + void backupLmk(); + + void recoverLmk(); + + void destroyLmk(); + + void checkLmk(); + + byte[] exportLmkSeedMac(); + + BackupDataResult backupLmkEx(int outBufferSize); + + void recoverLmkEx(byte[] lmkComponent); + + void generateIk(int keyType); + + void backupIk(int keyType); + + void recoverIk(int keyType); + + void destroyIk(int keyType); + + KeyStatusResult statusIk(int keyType); + + void generateUkey(UkeyGenerateRequest request); + + void loginUkey(UkeyLoginRequest request); + + void changeUkeyPin(UkeyPinChangeRequest request); + + void unlockUkey(UkeyUnlockRequest request); + + void readLmkComponent(byte[] ukeyPin); + + void readUkeyIkComponent(int keyType, byte[] ukeyPin); + + void generateCertificate(byte[] ukeyPin); + + void logoutAdmin(int adminIndex); + + LoginStatusResult loginStatus(); + + void createFile(FileCreateRequest request); + + void writeFile(FileWriteRequest request); + + BackupDataResult readFile(FileReadRequest request); + + void deleteFile(String fileName); +} diff --git a/src/main/java/com/cisd/tms/integration/file/package-info.java b/src/main/java/com/cisd/tms/integration/file/package-info.java new file mode 100644 index 0000000..58c1185 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/file/package-info.java @@ -0,0 +1,4 @@ +/** + * file integration adapters. + */ +package com.cisd.tms.integration.file; diff --git a/src/main/java/com/cisd/tms/integration/mq/package-info.java b/src/main/java/com/cisd/tms/integration/mq/package-info.java new file mode 100644 index 0000000..2467160 --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/mq/package-info.java @@ -0,0 +1,4 @@ +/** + * mq integration adapters. + */ +package com.cisd.tms.integration.mq; diff --git a/src/main/java/com/cisd/tms/integration/package-info.java b/src/main/java/com/cisd/tms/integration/package-info.java new file mode 100644 index 0000000..fe673dd --- /dev/null +++ b/src/main/java/com/cisd/tms/integration/package-info.java @@ -0,0 +1,4 @@ +/** + * External integrations (CIPS scripts, MQ, crypto devices, filesystem adapters). + */ +package com.cisd.tms.integration; diff --git a/src/main/java/com/cisd/tms/modules/activation/package-info.java b/src/main/java/com/cisd/tms/modules/activation/package-info.java new file mode 100644 index 0000000..368a56d --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/activation/package-info.java @@ -0,0 +1,4 @@ +/** + * activation module. + */ +package com.cisd.tms.modules.activation; diff --git a/src/main/java/com/cisd/tms/modules/audit/package-info.java b/src/main/java/com/cisd/tms/modules/audit/package-info.java new file mode 100644 index 0000000..703d507 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/audit/package-info.java @@ -0,0 +1,4 @@ +/** + * audit module. + */ +package com.cisd.tms.modules.audit; diff --git a/src/main/java/com/cisd/tms/modules/auth/controller/AuthInternalController.java b/src/main/java/com/cisd/tms/modules/auth/controller/AuthInternalController.java new file mode 100644 index 0000000..3e13acb --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/controller/AuthInternalController.java @@ -0,0 +1,35 @@ +package com.cisd.tms.modules.auth.controller; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.modules.auth.dto.CurrentUserResponse; +import com.cisd.tms.modules.auth.dto.LoginRequest; +import com.cisd.tms.modules.auth.dto.LoginResponse; +import com.cisd.tms.modules.auth.service.AuthService; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/auth") +public class AuthInternalController { + + private final AuthService authService; + + public AuthInternalController(AuthService authService) { + this.authService = authService; + } + + @PostMapping("/login") + public ApiResponse login(@Valid @RequestBody LoginRequest request) { + return ApiResponse.success(authService.login(request)); + } + + @GetMapping("/me") + public ApiResponse me(@RequestHeader(value = "X-User", required = false) String user) { + return ApiResponse.success(authService.me(user)); + } +} diff --git a/src/main/java/com/cisd/tms/modules/auth/dto/CurrentUserResponse.java b/src/main/java/com/cisd/tms/modules/auth/dto/CurrentUserResponse.java new file mode 100644 index 0000000..976a6bf --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/dto/CurrentUserResponse.java @@ -0,0 +1,32 @@ +package com.cisd.tms.modules.auth.dto; + +public class CurrentUserResponse { + + private String username; + private String displayName; + private String role; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } +} diff --git a/src/main/java/com/cisd/tms/modules/auth/dto/LoginRequest.java b/src/main/java/com/cisd/tms/modules/auth/dto/LoginRequest.java new file mode 100644 index 0000000..da97d99 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/dto/LoginRequest.java @@ -0,0 +1,28 @@ +package com.cisd.tms.modules.auth.dto; + +import jakarta.validation.constraints.NotBlank; + +public class LoginRequest { + + @NotBlank(message = "username is required") + private String username; + + @NotBlank(message = "password is required") + private String password; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/com/cisd/tms/modules/auth/dto/LoginResponse.java b/src/main/java/com/cisd/tms/modules/auth/dto/LoginResponse.java new file mode 100644 index 0000000..1341d1f --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/dto/LoginResponse.java @@ -0,0 +1,32 @@ +package com.cisd.tms.modules.auth.dto; + +public class LoginResponse { + + private String username; + private String token; + private String expiresAt; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getExpiresAt() { + return expiresAt; + } + + public void setExpiresAt(String expiresAt) { + this.expiresAt = expiresAt; + } +} diff --git a/src/main/java/com/cisd/tms/modules/auth/entity/AuthUserEntity.java b/src/main/java/com/cisd/tms/modules/auth/entity/AuthUserEntity.java new file mode 100644 index 0000000..1affcd4 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/entity/AuthUserEntity.java @@ -0,0 +1,36 @@ +package com.cisd.tms.modules.auth.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.cisd.tms.infrastructure.persistence.entity.BaseEntity; + +@TableName("tms_auth_user") +public class AuthUserEntity extends BaseEntity { + + private String username; + private String displayName; + private String role; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } +} diff --git a/src/main/java/com/cisd/tms/modules/auth/mapper/AuthUserMapper.java b/src/main/java/com/cisd/tms/modules/auth/mapper/AuthUserMapper.java new file mode 100644 index 0000000..de266ec --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/mapper/AuthUserMapper.java @@ -0,0 +1,12 @@ +package com.cisd.tms.modules.auth.mapper; + +import com.cisd.tms.infrastructure.persistence.mapper.BaseMapperX; +import com.cisd.tms.modules.auth.entity.AuthUserEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface AuthUserMapper extends BaseMapperX { + + AuthUserEntity selectByUsername(@Param("username") String username); +} diff --git a/src/main/java/com/cisd/tms/modules/auth/package-info.java b/src/main/java/com/cisd/tms/modules/auth/package-info.java new file mode 100644 index 0000000..bfa1e5a --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/package-info.java @@ -0,0 +1,4 @@ +/** + * auth module. + */ +package com.cisd.tms.modules.auth; diff --git a/src/main/java/com/cisd/tms/modules/auth/repository/AuthUserRepository.java b/src/main/java/com/cisd/tms/modules/auth/repository/AuthUserRepository.java new file mode 100644 index 0000000..ae4ca8b --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/repository/AuthUserRepository.java @@ -0,0 +1,9 @@ +package com.cisd.tms.modules.auth.repository; + +import com.cisd.tms.modules.auth.entity.AuthUserEntity; +import java.util.Optional; + +public interface AuthUserRepository { + + Optional findByUsername(String username); +} diff --git a/src/main/java/com/cisd/tms/modules/auth/repository/impl/AuthUserRepositoryImpl.java b/src/main/java/com/cisd/tms/modules/auth/repository/impl/AuthUserRepositoryImpl.java new file mode 100644 index 0000000..b7645b0 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/repository/impl/AuthUserRepositoryImpl.java @@ -0,0 +1,22 @@ +package com.cisd.tms.modules.auth.repository.impl; + +import com.cisd.tms.modules.auth.entity.AuthUserEntity; +import com.cisd.tms.modules.auth.mapper.AuthUserMapper; +import com.cisd.tms.modules.auth.repository.AuthUserRepository; +import java.util.Optional; +import org.springframework.stereotype.Repository; + +@Repository +public class AuthUserRepositoryImpl implements AuthUserRepository { + + private final AuthUserMapper authUserMapper; + + public AuthUserRepositoryImpl(AuthUserMapper authUserMapper) { + this.authUserMapper = authUserMapper; + } + + @Override + public Optional findByUsername(String username) { + return Optional.ofNullable(authUserMapper.selectByUsername(username)); + } +} diff --git a/src/main/java/com/cisd/tms/modules/auth/service/AuthService.java b/src/main/java/com/cisd/tms/modules/auth/service/AuthService.java new file mode 100644 index 0000000..32ae517 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/auth/service/AuthService.java @@ -0,0 +1,46 @@ +package com.cisd.tms.modules.auth.service; + +import com.cisd.tms.modules.auth.dto.CurrentUserResponse; +import com.cisd.tms.modules.auth.dto.LoginRequest; +import com.cisd.tms.modules.auth.dto.LoginResponse; +import com.cisd.tms.modules.auth.entity.AuthUserEntity; +import com.cisd.tms.modules.auth.repository.AuthUserRepository; +import java.time.OffsetDateTime; +import java.util.UUID; +import org.springframework.stereotype.Service; + +@Service +public class AuthService { + + private final AuthUserRepository authUserRepository; + + public AuthService(AuthUserRepository authUserRepository) { + this.authUserRepository = authUserRepository; + } + + public LoginResponse login(LoginRequest request) { + LoginResponse response = new LoginResponse(); + response.setUsername(request.getUsername()); + response.setToken("tms-" + UUID.randomUUID()); + response.setExpiresAt(OffsetDateTime.now().plusHours(8).toString()); + return response; + } + + public CurrentUserResponse me(String username) { + String normalized = username == null || username.isBlank() ? "admin" : username; + AuthUserEntity entity = authUserRepository.findByUsername(normalized).orElse(null); + + CurrentUserResponse response = new CurrentUserResponse(); + if (entity == null) { + response.setUsername(normalized); + response.setDisplayName("TMS Administrator"); + response.setRole("ADMIN"); + return response; + } + + response.setUsername(entity.getUsername()); + response.setDisplayName(entity.getDisplayName()); + response.setRole(entity.getRole()); + return response; + } +} diff --git a/src/main/java/com/cisd/tms/modules/backup/package-info.java b/src/main/java/com/cisd/tms/modules/backup/package-info.java new file mode 100644 index 0000000..30a2c5b --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/backup/package-info.java @@ -0,0 +1,4 @@ +/** + * backup module. + */ +package com.cisd.tms.modules.backup; diff --git a/src/main/java/com/cisd/tms/modules/cert/package-info.java b/src/main/java/com/cisd/tms/modules/cert/package-info.java new file mode 100644 index 0000000..c339fb4 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/cert/package-info.java @@ -0,0 +1,4 @@ +/** + * cert module. + */ +package com.cisd.tms.modules.cert; diff --git a/src/main/java/com/cisd/tms/modules/device/controller/CryptoCardInternalController.java b/src/main/java/com/cisd/tms/modules/device/controller/CryptoCardInternalController.java new file mode 100644 index 0000000..2da8d49 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/controller/CryptoCardInternalController.java @@ -0,0 +1,1142 @@ +package com.cisd.tms.modules.device.controller; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceConfResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceCountResult; +import com.cisd.tms.integration.crypto.pcie.model.DeviceInfoResult; +import com.cisd.tms.integration.crypto.pcie.model.DigestRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileCreateRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileReadRequest; +import com.cisd.tms.integration.crypto.pcie.model.FileWriteRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateAgreementDataAndKeyEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKekRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardEccKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardRsaKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacRequest; +import com.cisd.tms.integration.crypto.pcie.model.HmacResult; +import com.cisd.tms.integration.crypto.pcie.model.KeyStatusResult; +import com.cisd.tms.integration.crypto.pcie.model.MacCalcRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.SymmetricKekCryptoRequest; +import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult; +import com.cisd.tms.integration.crypto.pcie.service.PcieCryptoService; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import java.util.Arrays; +import java.util.Base64; +import java.util.Map; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@Validated +@RestController +@RequestMapping("/api/v1/device/crypto") +public class CryptoCardInternalController { + + private final PcieCryptoService pcieCryptoService; + + public CryptoCardInternalController(PcieCryptoService pcieCryptoService) { + this.pcieCryptoService = pcieCryptoService; + } + + @GetMapping("/device-count") + public ApiResponse getDeviceCount() { + return ApiResponse.success(pcieCryptoService.getDeviceCount()); + } + + @GetMapping("/device-conf") + public ApiResponse getDeviceConf() { + return ApiResponse.success(pcieCryptoService.getDeviceConf()); + } + + @GetMapping("/device-info") + public ApiResponse getDeviceInfo() { + return ApiResponse.success(pcieCryptoService.getDeviceInfo()); + } + + @GetMapping("/random") + public ApiResponse> random(@RequestParam(defaultValue = "16") @Min(1) int length) { + byte[] random = pcieCryptoService.generateRandom(length); + return ApiResponse.success(Map.of( + "length", random.length, + "randomBase64", Base64.getEncoder().encodeToString(random) + )); + } + + @PostMapping("/self-test") + public ApiResponse> selfTest() { + pcieCryptoService.deviceSelfTest(); + return ApiResponse.success(Map.of("passed", true)); + } + + @PostMapping("/hmac") + public ApiResponse> hmac(@Valid @RequestBody CryptoHmacInternalRequest request) { + HmacRequest hmacRequest = new HmacRequest(); + hmacRequest.setAlgId(request.getAlgId()); + hmacRequest.setKey(Base64.getDecoder().decode(request.getKeyBase64())); + hmacRequest.setData(Base64.getDecoder().decode(request.getDataBase64())); + + HmacResult result = pcieCryptoService.hmac(hmacRequest); + return ApiResponse.success(Map.of( + "hmacLength", result.getHmacLength(), + "hmacBase64", Base64.getEncoder().encodeToString(result.getHmac()) + )); + } + + @PostMapping("/digest") + public ApiResponse> digest(@Valid @RequestBody CryptoDigestInternalRequest request) { + DigestRequest digestRequest = new DigestRequest(); + digestRequest.setAlgId(request.getAlgId()); + digestRequest.setData(Base64.getDecoder().decode(request.getDataBase64())); + digestRequest.setOutBufferSize(request.getOutBufferSize()); + byte[] digest = pcieCryptoService.digest(digestRequest).getData(); + return ApiResponse.success(Map.of( + "digestLength", digest.length, + "digestBase64", Base64.getEncoder().encodeToString(digest) + )); + } + + @PostMapping("/encrypt/plain") + public ApiResponse> encryptPlain(@Valid @RequestBody CryptoSymmetricInternalRequest request) { + SymmetricCryptoRequest cryptoRequest = toSymmetricCryptoRequest(request); + byte[] data = pcieCryptoService.encryptWithPlainKey(cryptoRequest).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/decrypt/plain") + public ApiResponse> decryptPlain(@Valid @RequestBody CryptoSymmetricInternalRequest request) { + SymmetricCryptoRequest cryptoRequest = toSymmetricCryptoRequest(request); + byte[] data = pcieCryptoService.decryptWithPlainKey(cryptoRequest).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/encrypt/kek") + public ApiResponse> encryptKek(@Valid @RequestBody CryptoSymmetricKekInternalRequest request) { + SymmetricKekCryptoRequest cryptoRequest = toSymmetricKekCryptoRequest(request); + byte[] data = pcieCryptoService.encryptWithKekWrappedKey(cryptoRequest).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/decrypt/kek") + public ApiResponse> decryptKek(@Valid @RequestBody CryptoSymmetricKekInternalRequest request) { + SymmetricKekCryptoRequest cryptoRequest = toSymmetricKekCryptoRequest(request); + byte[] data = pcieCryptoService.decryptWithKekWrappedKey(cryptoRequest).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/mac/plain") + public ApiResponse> macPlain(@Valid @RequestBody CryptoMacInternalRequest request) { + MacCalcRequest macRequest = new MacCalcRequest(); + macRequest.setAlgId(request.getAlgId()); + macRequest.setKey(Base64.getDecoder().decode(request.getKeyBase64())); + macRequest.setIv(decodeNullableBase64(request.getIvBase64())); + macRequest.setData(Base64.getDecoder().decode(request.getDataBase64())); + macRequest.setOutBufferSize(request.getOutBufferSize()); + byte[] mac = pcieCryptoService.calculateMacWithPlainKey(macRequest).getData(); + return ApiResponse.success(Map.of( + "length", mac.length, + "macBase64", Base64.getEncoder().encodeToString(mac) + )); + } + + @PostMapping("/file/create") + public ApiResponse createFile(@Valid @RequestBody CryptoFileCreateInternalRequest request) { + FileCreateRequest fileCreateRequest = new FileCreateRequest(); + fileCreateRequest.setFileName(request.getFileName()); + fileCreateRequest.setFileSize(request.getFileSize()); + pcieCryptoService.createFile(fileCreateRequest); + return ApiResponse.success(); + } + + @PostMapping("/file/write") + public ApiResponse writeFile(@Valid @RequestBody CryptoFileWriteInternalRequest request) { + FileWriteRequest fileWriteRequest = new FileWriteRequest(); + fileWriteRequest.setFileName(request.getFileName()); + fileWriteRequest.setOffset(request.getOffset()); + fileWriteRequest.setData(Base64.getDecoder().decode(request.getDataBase64())); + pcieCryptoService.writeFile(fileWriteRequest); + return ApiResponse.success(); + } + + @PostMapping("/file/read") + public ApiResponse> readFile(@Valid @RequestBody CryptoFileReadInternalRequest request) { + FileReadRequest fileReadRequest = new FileReadRequest(); + fileReadRequest.setFileName(request.getFileName()); + fileReadRequest.setOffset(request.getOffset()); + fileReadRequest.setReadLength(request.getReadLength()); + byte[] data = pcieCryptoService.readFile(fileReadRequest).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/file/delete") + public ApiResponse deleteFile(@Valid @RequestBody CryptoFileDeleteInternalRequest request) { + pcieCryptoService.deleteFile(request.getFileName()); + return ApiResponse.success(); + } + + @PostMapping("/kek/generate") + public ApiResponse generateKek(@Valid @RequestBody CryptoGenerateKekInternalRequest request) { + GenerateKekRequest generateKekRequest = new GenerateKekRequest(); + generateKekRequest.setKeyBits(request.getKeyBits()); + generateKekRequest.setKeyIndex(request.getKeyIndex()); + pcieCryptoService.generateKek(generateKekRequest); + return ApiResponse.success(); + } + + @GetMapping("/kek/status") + public ApiResponse kekStatus(@RequestParam @Min(0) int keyIndex) { + return ApiResponse.success(pcieCryptoService.statusKek(keyIndex)); + } + + @GetMapping("/lmk/seed-mac") + public ApiResponse> exportLmkSeedMac() { + byte[] mac = pcieCryptoService.exportLmkSeedMac(); + return ApiResponse.success(Map.of( + "length", mac.length, + "macBase64", Base64.getEncoder().encodeToString(mac) + )); + } + + @PostMapping("/std/keypair/rsa") + public ApiResponse> generateStandardRsaKeyPair( + @Valid @RequestBody CryptoGenerateStandardRsaKeyPairInternalRequest request + ) { + GenerateStandardRsaKeyPairRequest req = new GenerateStandardRsaKeyPairRequest(); + req.setKeyBits(request.getKeyBits()); + req.setPublicKeyBufferSize(request.getPublicKeyBufferSize()); + req.setPrivateKeyBufferSize(request.getPrivateKeyBufferSize()); + StandardKeyPairResult result = pcieCryptoService.generateStandardRsaKeyPair(req); + return ApiResponse.success(Map.of( + "publicKeyLength", result.getPublicKeyLength(), + "publicKeyBase64", Base64.getEncoder().encodeToString(result.getPublicKey()), + "privateKeyLength", result.getPrivateKeyLength(), + "privateKeyBase64", Base64.getEncoder().encodeToString(result.getPrivateKey()) + )); + } + + @PostMapping("/std/keypair/ecc") + public ApiResponse> generateStandardEccKeyPair( + @Valid @RequestBody CryptoGenerateStandardEccKeyPairInternalRequest request + ) { + GenerateStandardEccKeyPairRequest req = new GenerateStandardEccKeyPairRequest(); + req.setAlgId(request.getAlgId()); + req.setKeyBits(request.getKeyBits()); + req.setPublicKeyBufferSize(request.getPublicKeyBufferSize()); + req.setPrivateKeyBufferSize(request.getPrivateKeyBufferSize()); + StandardKeyPairResult result = pcieCryptoService.generateStandardEccKeyPair(req); + return ApiResponse.success(Map.of( + "publicKeyLength", result.getPublicKeyLength(), + "publicKeyBase64", Base64.getEncoder().encodeToString(result.getPublicKey()), + "privateKeyLength", result.getPrivateKeyLength(), + "privateKeyBase64", Base64.getEncoder().encodeToString(result.getPrivateKey()) + )); + } + + @PostMapping("/envelope/exchange/rsa") + public ApiResponse> exchangeEnvelopeRsa( + @Valid @RequestBody CryptoExchangeEnvelopeRsaInternalRequest request + ) { + ExchangeDigitEnvelopeRsaRequest req = new ExchangeDigitEnvelopeRsaRequest(); + req.setKeyIndex(request.getKeyIndex()); + req.setPublicKeyBlob(Base64.getDecoder().decode(request.getPublicKeyBase64())); + req.setInputEnvelopeBlob(Base64.getDecoder().decode(request.getInputEnvelopeBase64())); + req.setOutBufferSize(request.getOutBufferSize()); + byte[] data = pcieCryptoService.exchangeDigitEnvelopeBaseOnRsa(req).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/envelope/exchange/ecc") + public ApiResponse> exchangeEnvelopeEcc( + @Valid @RequestBody CryptoExchangeEnvelopeEccInternalRequest request + ) { + ExchangeDigitEnvelopeEccRequest req = new ExchangeDigitEnvelopeEccRequest(); + req.setKeyIndex(request.getKeyIndex()); + req.setAlgId(request.getAlgId()); + req.setPublicKeyBlob(Base64.getDecoder().decode(request.getPublicKeyBase64())); + req.setInputEnvelopeBlob(Base64.getDecoder().decode(request.getInputEnvelopeBase64())); + req.setOutBufferSize(request.getOutBufferSize()); + byte[] data = pcieCryptoService.exchangeDigitEnvelopeBaseOnEcc(req).getData(); + return ApiResponse.success(Map.of( + "length", data.length, + "dataBase64", Base64.getEncoder().encodeToString(data) + )); + } + + @PostMapping("/agreement/data-key/ecc") + public ApiResponse> generateAgreementDataAndKeyEcc( + @Valid @RequestBody CryptoGenerateAgreementDataAndKeyEccInternalRequest request + ) { + GenerateAgreementDataAndKeyEccRequest req = new GenerateAgreementDataAndKeyEccRequest(); + req.setIskIndex(request.getIskIndex()); + req.setKeyBits(request.getKeyBits()); + req.setResponseId(Base64.getDecoder().decode(request.getResponseIdBase64())); + req.setSponsorId(Base64.getDecoder().decode(request.getSponsorIdBase64())); + req.setSponsorPublicKeyBlob(Base64.getDecoder().decode(request.getSponsorPublicKeyBase64())); + req.setSponsorTmpPublicKeyBlob(Base64.getDecoder().decode(request.getSponsorTmpPublicKeyBase64())); + req.setResponsePublicKeyBufferSize(request.getResponsePublicKeyBufferSize()); + req.setResponseTmpPublicKeyBufferSize(request.getResponseTmpPublicKeyBufferSize()); + AgreementDataAndKeyEccResult result = pcieCryptoService.generateAgreementDataAndKeyWithEcc(req); + return ApiResponse.success(Map.of( + "responsePublicKeyLength", result.getResponsePublicKeyLength(), + "responsePublicKeyBase64", Base64.getEncoder().encodeToString(result.getResponsePublicKey()), + "responseTmpPublicKeyLength", result.getResponseTmpPublicKeyLength(), + "responseTmpPublicKeyBase64", Base64.getEncoder().encodeToString(result.getResponseTmpPublicKey()), + "sessionKeyGenerated", result.isSessionKeyGenerated() + )); + } + + @PostMapping("/agreement/session-key/ecc") + public ApiResponse> generateSessionKeyEcc( + @Valid @RequestBody CryptoGenerateSessionKeyEccInternalRequest request + ) { + EccAgreementSessionKeyRequest req = new EccAgreementSessionKeyRequest(); + req.setIskIndex(request.getIskIndex()); + req.setKeyBits(request.getKeyBits()); + req.setSponsorId(Base64.getDecoder().decode(request.getSponsorIdBase64())); + req.setResponseId(Base64.getDecoder().decode(request.getResponseIdBase64())); + req.setResponsePublicKeyBlob(Base64.getDecoder().decode(request.getResponsePublicKeyBase64())); + req.setResponseTmpPublicKeyBlob(Base64.getDecoder().decode(request.getResponseTmpPublicKeyBase64())); + req.setSponsorPublicKeyBufferSize(request.getSponsorPublicKeyBufferSize()); + req.setSponsorTmpPublicKeyBufferSize(request.getSponsorTmpPublicKeyBufferSize()); + req.setSessionKeyBufferSize(request.getSessionKeyBufferSize()); + EccAgreementSessionKeyResult result = pcieCryptoService.generateSessionKeyWithEccAgreement(req); + return ApiResponse.success(Map.of( + "sponsorPublicKeyLength", result.getSponsorPublicKeyLength(), + "sponsorPublicKeyBase64", Base64.getEncoder().encodeToString(result.getSponsorPublicKey()), + "sponsorTmpPublicKeyLength", result.getSponsorTmpPublicKeyLength(), + "sponsorTmpPublicKeyBase64", Base64.getEncoder().encodeToString(result.getSponsorTmpPublicKey()), + "sessionKeyLength", result.getSessionKeyLength(), + "sessionKeyBase64", Base64.getEncoder().encodeToString(result.getSessionKey()), + "sessionKeyGenerated", result.isSessionKeyGenerated() + )); + } + + private static SymmetricCryptoRequest toSymmetricCryptoRequest(CryptoSymmetricInternalRequest request) { + SymmetricCryptoRequest cryptoRequest = new SymmetricCryptoRequest(); + cryptoRequest.setAlgId(request.getAlgId()); + cryptoRequest.setKey(Base64.getDecoder().decode(request.getKeyBase64())); + cryptoRequest.setIv(decodeNullableBase64(request.getIvBase64())); + cryptoRequest.setData(Base64.getDecoder().decode(request.getDataBase64())); + cryptoRequest.setOutBufferSize(request.getOutBufferSize()); + return cryptoRequest; + } + + private static SymmetricKekCryptoRequest toSymmetricKekCryptoRequest(CryptoSymmetricKekInternalRequest request) { + SymmetricKekCryptoRequest cryptoRequest = new SymmetricKekCryptoRequest(); + cryptoRequest.setAlgId(request.getAlgId()); + cryptoRequest.setKekIndex(request.getKekIndex()); + cryptoRequest.setWrappedKey(Base64.getDecoder().decode(request.getWrappedKeyBase64())); + cryptoRequest.setIv(decodeNullableBase64(request.getIvBase64())); + cryptoRequest.setData(Base64.getDecoder().decode(request.getDataBase64())); + cryptoRequest.setOutBufferSize(request.getOutBufferSize()); + return cryptoRequest; + } + + private static byte[] decodeNullableBase64(String value) { + if (value == null || value.isBlank()) { + return null; + } + byte[] decoded = Base64.getDecoder().decode(value); + return decoded.length == 0 ? null : Arrays.copyOf(decoded, decoded.length); + } + + public static class CryptoHmacInternalRequest { + + @Min(1) + private int algId; + + @NotBlank + private String keyBase64; + + @NotBlank + private String dataBase64; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public String getKeyBase64() { + return keyBase64; + } + + public void setKeyBase64(String keyBase64) { + this.keyBase64 = keyBase64; + } + + public String getDataBase64() { + return dataBase64; + } + + public void setDataBase64(String dataBase64) { + this.dataBase64 = dataBase64; + } + } + + public static class CryptoGenerateKekInternalRequest { + + @Min(1) + private int keyBits; + + @Min(0) + private int keyIndex; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + } + + public static class CryptoGenerateStandardRsaKeyPairInternalRequest { + + @Min(1) + private int keyBits; + + @Min(1) + private int publicKeyBufferSize; + + @Min(1) + private int privateKeyBufferSize; + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getPublicKeyBufferSize() { + return publicKeyBufferSize; + } + + public void setPublicKeyBufferSize(int publicKeyBufferSize) { + this.publicKeyBufferSize = publicKeyBufferSize; + } + + public int getPrivateKeyBufferSize() { + return privateKeyBufferSize; + } + + public void setPrivateKeyBufferSize(int privateKeyBufferSize) { + this.privateKeyBufferSize = privateKeyBufferSize; + } + } + + public static class CryptoGenerateStandardEccKeyPairInternalRequest { + + @Min(1) + private int algId; + + @Min(1) + private int keyBits; + + @Min(1) + private int publicKeyBufferSize; + + @Min(1) + private int privateKeyBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public int getPublicKeyBufferSize() { + return publicKeyBufferSize; + } + + public void setPublicKeyBufferSize(int publicKeyBufferSize) { + this.publicKeyBufferSize = publicKeyBufferSize; + } + + public int getPrivateKeyBufferSize() { + return privateKeyBufferSize; + } + + public void setPrivateKeyBufferSize(int privateKeyBufferSize) { + this.privateKeyBufferSize = privateKeyBufferSize; + } + } + + public static class CryptoExchangeEnvelopeRsaInternalRequest { + + @Min(0) + private int keyIndex; + + @NotBlank + private String publicKeyBase64; + + @NotBlank + private String inputEnvelopeBase64; + + @Min(1) + private int outBufferSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public String getPublicKeyBase64() { + return publicKeyBase64; + } + + public void setPublicKeyBase64(String publicKeyBase64) { + this.publicKeyBase64 = publicKeyBase64; + } + + public String getInputEnvelopeBase64() { + return inputEnvelopeBase64; + } + + public void setInputEnvelopeBase64(String inputEnvelopeBase64) { + this.inputEnvelopeBase64 = inputEnvelopeBase64; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } + } + + public static class CryptoExchangeEnvelopeEccInternalRequest { + + @Min(0) + private int keyIndex; + + @Min(1) + private int algId; + + @NotBlank + private String publicKeyBase64; + + @NotBlank + private String inputEnvelopeBase64; + + @Min(1) + private int outBufferSize; + + public int getKeyIndex() { + return keyIndex; + } + + public void setKeyIndex(int keyIndex) { + this.keyIndex = keyIndex; + } + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public String getPublicKeyBase64() { + return publicKeyBase64; + } + + public void setPublicKeyBase64(String publicKeyBase64) { + this.publicKeyBase64 = publicKeyBase64; + } + + public String getInputEnvelopeBase64() { + return inputEnvelopeBase64; + } + + public void setInputEnvelopeBase64(String inputEnvelopeBase64) { + this.inputEnvelopeBase64 = inputEnvelopeBase64; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } + } + + public static class CryptoGenerateAgreementDataAndKeyEccInternalRequest { + + @Min(0) + private int iskIndex; + + @Min(1) + private int keyBits; + + @NotBlank + private String responseIdBase64; + + @NotBlank + private String sponsorIdBase64; + + @NotBlank + private String sponsorPublicKeyBase64; + + @NotBlank + private String sponsorTmpPublicKeyBase64; + + @Min(1) + private int responsePublicKeyBufferSize; + + @Min(1) + private int responseTmpPublicKeyBufferSize; + + public int getIskIndex() { + return iskIndex; + } + + public void setIskIndex(int iskIndex) { + this.iskIndex = iskIndex; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public String getResponseIdBase64() { + return responseIdBase64; + } + + public void setResponseIdBase64(String responseIdBase64) { + this.responseIdBase64 = responseIdBase64; + } + + public String getSponsorIdBase64() { + return sponsorIdBase64; + } + + public void setSponsorIdBase64(String sponsorIdBase64) { + this.sponsorIdBase64 = sponsorIdBase64; + } + + public String getSponsorPublicKeyBase64() { + return sponsorPublicKeyBase64; + } + + public void setSponsorPublicKeyBase64(String sponsorPublicKeyBase64) { + this.sponsorPublicKeyBase64 = sponsorPublicKeyBase64; + } + + public String getSponsorTmpPublicKeyBase64() { + return sponsorTmpPublicKeyBase64; + } + + public void setSponsorTmpPublicKeyBase64(String sponsorTmpPublicKeyBase64) { + this.sponsorTmpPublicKeyBase64 = sponsorTmpPublicKeyBase64; + } + + public int getResponsePublicKeyBufferSize() { + return responsePublicKeyBufferSize; + } + + public void setResponsePublicKeyBufferSize(int responsePublicKeyBufferSize) { + this.responsePublicKeyBufferSize = responsePublicKeyBufferSize; + } + + public int getResponseTmpPublicKeyBufferSize() { + return responseTmpPublicKeyBufferSize; + } + + public void setResponseTmpPublicKeyBufferSize(int responseTmpPublicKeyBufferSize) { + this.responseTmpPublicKeyBufferSize = responseTmpPublicKeyBufferSize; + } + } + + public static class CryptoGenerateSessionKeyEccInternalRequest { + + @Min(0) + private int iskIndex; + + @Min(1) + private int keyBits; + + @NotBlank + private String sponsorIdBase64; + + @NotBlank + private String responseIdBase64; + + @NotBlank + private String responsePublicKeyBase64; + + @NotBlank + private String responseTmpPublicKeyBase64; + + @Min(1) + private int sponsorPublicKeyBufferSize; + + @Min(1) + private int sponsorTmpPublicKeyBufferSize; + + @Min(1) + private int sessionKeyBufferSize; + + public int getIskIndex() { + return iskIndex; + } + + public void setIskIndex(int iskIndex) { + this.iskIndex = iskIndex; + } + + public int getKeyBits() { + return keyBits; + } + + public void setKeyBits(int keyBits) { + this.keyBits = keyBits; + } + + public String getSponsorIdBase64() { + return sponsorIdBase64; + } + + public void setSponsorIdBase64(String sponsorIdBase64) { + this.sponsorIdBase64 = sponsorIdBase64; + } + + public String getResponseIdBase64() { + return responseIdBase64; + } + + public void setResponseIdBase64(String responseIdBase64) { + this.responseIdBase64 = responseIdBase64; + } + + public String getResponsePublicKeyBase64() { + return responsePublicKeyBase64; + } + + public void setResponsePublicKeyBase64(String responsePublicKeyBase64) { + this.responsePublicKeyBase64 = responsePublicKeyBase64; + } + + public String getResponseTmpPublicKeyBase64() { + return responseTmpPublicKeyBase64; + } + + public void setResponseTmpPublicKeyBase64(String responseTmpPublicKeyBase64) { + this.responseTmpPublicKeyBase64 = responseTmpPublicKeyBase64; + } + + public int getSponsorPublicKeyBufferSize() { + return sponsorPublicKeyBufferSize; + } + + public void setSponsorPublicKeyBufferSize(int sponsorPublicKeyBufferSize) { + this.sponsorPublicKeyBufferSize = sponsorPublicKeyBufferSize; + } + + public int getSponsorTmpPublicKeyBufferSize() { + return sponsorTmpPublicKeyBufferSize; + } + + public void setSponsorTmpPublicKeyBufferSize(int sponsorTmpPublicKeyBufferSize) { + this.sponsorTmpPublicKeyBufferSize = sponsorTmpPublicKeyBufferSize; + } + + public int getSessionKeyBufferSize() { + return sessionKeyBufferSize; + } + + public void setSessionKeyBufferSize(int sessionKeyBufferSize) { + this.sessionKeyBufferSize = sessionKeyBufferSize; + } + } + + public static class CryptoDigestInternalRequest { + + @Min(1) + private int algId; + + @NotBlank + private String dataBase64; + + @Min(1) + private int outBufferSize = 64; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public String getDataBase64() { + return dataBase64; + } + + public void setDataBase64(String dataBase64) { + this.dataBase64 = dataBase64; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } + } + + public static class CryptoSymmetricInternalRequest { + + @Min(1) + private int algId; + + @NotBlank + private String keyBase64; + + private String ivBase64; + + @NotBlank + private String dataBase64; + + @Min(1) + private int outBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public String getKeyBase64() { + return keyBase64; + } + + public void setKeyBase64(String keyBase64) { + this.keyBase64 = keyBase64; + } + + public String getIvBase64() { + return ivBase64; + } + + public void setIvBase64(String ivBase64) { + this.ivBase64 = ivBase64; + } + + public String getDataBase64() { + return dataBase64; + } + + public void setDataBase64(String dataBase64) { + this.dataBase64 = dataBase64; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } + } + + public static class CryptoSymmetricKekInternalRequest { + + @Min(1) + private int algId; + + @Min(0) + private int kekIndex; + + @NotBlank + private String wrappedKeyBase64; + + private String ivBase64; + + @NotBlank + private String dataBase64; + + @Min(1) + private int outBufferSize; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public int getKekIndex() { + return kekIndex; + } + + public void setKekIndex(int kekIndex) { + this.kekIndex = kekIndex; + } + + public String getWrappedKeyBase64() { + return wrappedKeyBase64; + } + + public void setWrappedKeyBase64(String wrappedKeyBase64) { + this.wrappedKeyBase64 = wrappedKeyBase64; + } + + public String getIvBase64() { + return ivBase64; + } + + public void setIvBase64(String ivBase64) { + this.ivBase64 = ivBase64; + } + + public String getDataBase64() { + return dataBase64; + } + + public void setDataBase64(String dataBase64) { + this.dataBase64 = dataBase64; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } + } + + public static class CryptoMacInternalRequest { + + @Min(1) + private int algId; + + @NotBlank + private String keyBase64; + + private String ivBase64; + + @NotBlank + private String dataBase64; + + @Min(1) + private int outBufferSize = 32; + + public int getAlgId() { + return algId; + } + + public void setAlgId(int algId) { + this.algId = algId; + } + + public String getKeyBase64() { + return keyBase64; + } + + public void setKeyBase64(String keyBase64) { + this.keyBase64 = keyBase64; + } + + public String getIvBase64() { + return ivBase64; + } + + public void setIvBase64(String ivBase64) { + this.ivBase64 = ivBase64; + } + + public String getDataBase64() { + return dataBase64; + } + + public void setDataBase64(String dataBase64) { + this.dataBase64 = dataBase64; + } + + public int getOutBufferSize() { + return outBufferSize; + } + + public void setOutBufferSize(int outBufferSize) { + this.outBufferSize = outBufferSize; + } + } + + public static class CryptoFileCreateInternalRequest { + + @NotBlank + private String fileName; + + @Min(1) + private int fileSize; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getFileSize() { + return fileSize; + } + + public void setFileSize(int fileSize) { + this.fileSize = fileSize; + } + } + + public static class CryptoFileWriteInternalRequest { + + @NotBlank + private String fileName; + + @Min(0) + private int offset; + + @NotBlank + private String dataBase64; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public String getDataBase64() { + return dataBase64; + } + + public void setDataBase64(String dataBase64) { + this.dataBase64 = dataBase64; + } + } + + public static class CryptoFileReadInternalRequest { + + @NotBlank + private String fileName; + + @Min(0) + private int offset; + + @Min(1) + private int readLength; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public int getReadLength() { + return readLength; + } + + public void setReadLength(int readLength) { + this.readLength = readLength; + } + } + + public static class CryptoFileDeleteInternalRequest { + + @NotBlank + private String fileName; + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + } +} diff --git a/src/main/java/com/cisd/tms/modules/device/controller/DeviceInternalController.java b/src/main/java/com/cisd/tms/modules/device/controller/DeviceInternalController.java new file mode 100644 index 0000000..7ec5d24 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/controller/DeviceInternalController.java @@ -0,0 +1,32 @@ +package com.cisd.tms.modules.device.controller; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.modules.device.dto.DeviceActionResponse; +import com.cisd.tms.modules.device.dto.DeviceInfoResponse; +import com.cisd.tms.modules.device.service.DeviceService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/device") +public class DeviceInternalController { + + private final DeviceService deviceService; + + public DeviceInternalController(DeviceService deviceService) { + this.deviceService = deviceService; + } + + @GetMapping("/info") + public ApiResponse info() { + return ApiResponse.success(deviceService.info()); + } + + @PostMapping("/restart") + public ApiResponse restart(@RequestHeader(value = "X-User", required = false) String operator) { + return ApiResponse.success(deviceService.restart(operator)); + } +} diff --git a/src/main/java/com/cisd/tms/modules/device/dto/DeviceActionResponse.java b/src/main/java/com/cisd/tms/modules/device/dto/DeviceActionResponse.java new file mode 100644 index 0000000..7a9ec26 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/dto/DeviceActionResponse.java @@ -0,0 +1,41 @@ +package com.cisd.tms.modules.device.dto; + +public class DeviceActionResponse { + + private String action; + private boolean accepted; + private String operator; + private String acceptedAt; + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public boolean isAccepted() { + return accepted; + } + + public void setAccepted(boolean accepted) { + this.accepted = accepted; + } + + public String getOperator() { + return operator; + } + + public void setOperator(String operator) { + this.operator = operator; + } + + public String getAcceptedAt() { + return acceptedAt; + } + + public void setAcceptedAt(String acceptedAt) { + this.acceptedAt = acceptedAt; + } +} diff --git a/src/main/java/com/cisd/tms/modules/device/dto/DeviceInfoResponse.java b/src/main/java/com/cisd/tms/modules/device/dto/DeviceInfoResponse.java new file mode 100644 index 0000000..e43f59e --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/dto/DeviceInfoResponse.java @@ -0,0 +1,32 @@ +package com.cisd.tms.modules.device.dto; + +public class DeviceInfoResponse { + + private String deviceId; + private String status; + private String version; + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } +} diff --git a/src/main/java/com/cisd/tms/modules/device/entity/DeviceNodeEntity.java b/src/main/java/com/cisd/tms/modules/device/entity/DeviceNodeEntity.java new file mode 100644 index 0000000..7291874 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/entity/DeviceNodeEntity.java @@ -0,0 +1,36 @@ +package com.cisd.tms.modules.device.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.cisd.tms.infrastructure.persistence.entity.BaseEntity; + +@TableName("tms_device_node") +public class DeviceNodeEntity extends BaseEntity { + + private String nodeId; + private String host; + private String status; + + public String getNodeId() { + return nodeId; + } + + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/src/main/java/com/cisd/tms/modules/device/mapper/DeviceNodeMapper.java b/src/main/java/com/cisd/tms/modules/device/mapper/DeviceNodeMapper.java new file mode 100644 index 0000000..e4b90b7 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/mapper/DeviceNodeMapper.java @@ -0,0 +1,12 @@ +package com.cisd.tms.modules.device.mapper; + +import com.cisd.tms.infrastructure.persistence.mapper.BaseMapperX; +import com.cisd.tms.modules.device.entity.DeviceNodeEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface DeviceNodeMapper extends BaseMapperX { + + DeviceNodeEntity selectByNodeId(@Param("nodeId") String nodeId); +} diff --git a/src/main/java/com/cisd/tms/modules/device/package-info.java b/src/main/java/com/cisd/tms/modules/device/package-info.java new file mode 100644 index 0000000..aeff503 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/package-info.java @@ -0,0 +1,4 @@ +/** + * device module. + */ +package com.cisd.tms.modules.device; diff --git a/src/main/java/com/cisd/tms/modules/device/repository/DeviceNodeRepository.java b/src/main/java/com/cisd/tms/modules/device/repository/DeviceNodeRepository.java new file mode 100644 index 0000000..19c72bf --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/repository/DeviceNodeRepository.java @@ -0,0 +1,9 @@ +package com.cisd.tms.modules.device.repository; + +import com.cisd.tms.modules.device.entity.DeviceNodeEntity; +import java.util.Optional; + +public interface DeviceNodeRepository { + + Optional findByNodeId(String nodeId); +} diff --git a/src/main/java/com/cisd/tms/modules/device/repository/impl/DeviceNodeRepositoryImpl.java b/src/main/java/com/cisd/tms/modules/device/repository/impl/DeviceNodeRepositoryImpl.java new file mode 100644 index 0000000..1fdd36b --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/repository/impl/DeviceNodeRepositoryImpl.java @@ -0,0 +1,22 @@ +package com.cisd.tms.modules.device.repository.impl; + +import com.cisd.tms.modules.device.entity.DeviceNodeEntity; +import com.cisd.tms.modules.device.mapper.DeviceNodeMapper; +import com.cisd.tms.modules.device.repository.DeviceNodeRepository; +import java.util.Optional; +import org.springframework.stereotype.Repository; + +@Repository +public class DeviceNodeRepositoryImpl implements DeviceNodeRepository { + + private final DeviceNodeMapper deviceNodeMapper; + + public DeviceNodeRepositoryImpl(DeviceNodeMapper deviceNodeMapper) { + this.deviceNodeMapper = deviceNodeMapper; + } + + @Override + public Optional findByNodeId(String nodeId) { + return Optional.ofNullable(deviceNodeMapper.selectByNodeId(nodeId)); + } +} diff --git a/src/main/java/com/cisd/tms/modules/device/service/DeviceService.java b/src/main/java/com/cisd/tms/modules/device/service/DeviceService.java new file mode 100644 index 0000000..8914c2e --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/device/service/DeviceService.java @@ -0,0 +1,44 @@ +package com.cisd.tms.modules.device.service; + +import com.cisd.tms.modules.device.dto.DeviceActionResponse; +import com.cisd.tms.modules.device.dto.DeviceInfoResponse; +import com.cisd.tms.modules.device.entity.DeviceNodeEntity; +import com.cisd.tms.modules.device.repository.DeviceNodeRepository; +import java.time.OffsetDateTime; +import org.springframework.stereotype.Service; + +@Service +public class DeviceService { + + private final DeviceNodeRepository deviceNodeRepository; + + public DeviceService(DeviceNodeRepository deviceNodeRepository) { + this.deviceNodeRepository = deviceNodeRepository; + } + + public DeviceInfoResponse info() { + DeviceNodeEntity entity = deviceNodeRepository.findByNodeId("node-01").orElse(null); + + DeviceInfoResponse response = new DeviceInfoResponse(); + if (entity == null) { + response.setDeviceId("cisd-all-in-one-001"); + response.setStatus("RUNNING"); + response.setVersion("0.0.1-SNAPSHOT"); + return response; + } + + response.setDeviceId(entity.getNodeId()); + response.setStatus(entity.getStatus()); + response.setVersion("db-loaded"); + return response; + } + + public DeviceActionResponse restart(String operator) { + DeviceActionResponse response = new DeviceActionResponse(); + response.setAction("RESTART"); + response.setAccepted(true); + response.setOperator(operator == null || operator.isBlank() ? "unknown" : operator); + response.setAcceptedAt(OffsetDateTime.now().toString()); + return response; + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java b/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java new file mode 100644 index 0000000..87dfefd --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/controller/InitInternalController.java @@ -0,0 +1,35 @@ +package com.cisd.tms.modules.init.controller; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.modules.init.dto.InitPlanTemplateResponse; +import com.cisd.tms.modules.init.dto.InitPreviewRequest; +import com.cisd.tms.modules.init.dto.InitPreviewResponse; +import com.cisd.tms.modules.init.service.InitService; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/init") +public class InitInternalController { + + private final InitService initService; + + public InitInternalController(InitService initService) { + this.initService = initService; + } + + @GetMapping("/template") + public ApiResponse template(@RequestParam(required = false) String version) { + return ApiResponse.success(initService.loadTemplate(version)); + } + + @PostMapping("/preview") + public ApiResponse preview(@Valid @RequestBody InitPreviewRequest request) { + return ApiResponse.success(initService.preview(request)); + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/dto/InitPlanTemplateResponse.java b/src/main/java/com/cisd/tms/modules/init/dto/InitPlanTemplateResponse.java new file mode 100644 index 0000000..3022c1c --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/dto/InitPlanTemplateResponse.java @@ -0,0 +1,34 @@ +package com.cisd.tms.modules.init.dto; + +import java.util.List; + +public class InitPlanTemplateResponse { + + private String version; + private List supportedVersions; + private String templatePath; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getSupportedVersions() { + return supportedVersions; + } + + public void setSupportedVersions(List supportedVersions) { + this.supportedVersions = supportedVersions; + } + + public String getTemplatePath() { + return templatePath; + } + + public void setTemplatePath(String templatePath) { + this.templatePath = templatePath; + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java b/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java new file mode 100644 index 0000000..1417a3d --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewRequest.java @@ -0,0 +1,31 @@ +package com.cisd.tms.modules.init.dto; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; + +public class InitPreviewRequest { + + @NotBlank(message = "version is required") + private String version; + + @Min(value = 1, message = "nodeCount must be >= 1") + @Max(value = 4, message = "nodeCount must be <= 4") + private int nodeCount; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public int getNodeCount() { + return nodeCount; + } + + public void setNodeCount(int nodeCount) { + this.nodeCount = nodeCount; + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewResponse.java b/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewResponse.java new file mode 100644 index 0000000..9831c12 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/dto/InitPreviewResponse.java @@ -0,0 +1,32 @@ +package com.cisd.tms.modules.init.dto; + +public class InitPreviewResponse { + + private String version; + private int stepCount; + private String summary; + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public int getStepCount() { + return stepCount; + } + + public void setStepCount(int stepCount) { + this.stepCount = stepCount; + } + + public String getSummary() { + return summary; + } + + public void setSummary(String summary) { + this.summary = summary; + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/entity/InitTaskEntity.java b/src/main/java/com/cisd/tms/modules/init/entity/InitTaskEntity.java new file mode 100644 index 0000000..704f513 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/entity/InitTaskEntity.java @@ -0,0 +1,36 @@ +package com.cisd.tms.modules.init.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.cisd.tms.infrastructure.persistence.entity.BaseEntity; + +@TableName("tms_init_task") +public class InitTaskEntity extends BaseEntity { + + private String taskId; + private String version; + private String status; + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/mapper/InitTaskMapper.java b/src/main/java/com/cisd/tms/modules/init/mapper/InitTaskMapper.java new file mode 100644 index 0000000..edf2d9a --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/mapper/InitTaskMapper.java @@ -0,0 +1,12 @@ +package com.cisd.tms.modules.init.mapper; + +import com.cisd.tms.infrastructure.persistence.mapper.BaseMapperX; +import com.cisd.tms.modules.init.entity.InitTaskEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface InitTaskMapper extends BaseMapperX { + + InitTaskEntity selectByTaskId(@Param("taskId") String taskId); +} diff --git a/src/main/java/com/cisd/tms/modules/init/package-info.java b/src/main/java/com/cisd/tms/modules/init/package-info.java new file mode 100644 index 0000000..1c1d306 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/package-info.java @@ -0,0 +1,4 @@ +/** + * init module. + */ +package com.cisd.tms.modules.init; diff --git a/src/main/java/com/cisd/tms/modules/init/repository/InitTaskRepository.java b/src/main/java/com/cisd/tms/modules/init/repository/InitTaskRepository.java new file mode 100644 index 0000000..f72c4f1 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/repository/InitTaskRepository.java @@ -0,0 +1,9 @@ +package com.cisd.tms.modules.init.repository; + +import com.cisd.tms.modules.init.entity.InitTaskEntity; +import java.util.Optional; + +public interface InitTaskRepository { + + Optional findByTaskId(String taskId); +} diff --git a/src/main/java/com/cisd/tms/modules/init/repository/impl/InitTaskRepositoryImpl.java b/src/main/java/com/cisd/tms/modules/init/repository/impl/InitTaskRepositoryImpl.java new file mode 100644 index 0000000..65b417e --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/repository/impl/InitTaskRepositoryImpl.java @@ -0,0 +1,22 @@ +package com.cisd.tms.modules.init.repository.impl; + +import com.cisd.tms.modules.init.entity.InitTaskEntity; +import com.cisd.tms.modules.init.mapper.InitTaskMapper; +import com.cisd.tms.modules.init.repository.InitTaskRepository; +import java.util.Optional; +import org.springframework.stereotype.Repository; + +@Repository +public class InitTaskRepositoryImpl implements InitTaskRepository { + + private final InitTaskMapper initTaskMapper; + + public InitTaskRepositoryImpl(InitTaskMapper initTaskMapper) { + this.initTaskMapper = initTaskMapper; + } + + @Override + public Optional findByTaskId(String taskId) { + return Optional.ofNullable(initTaskMapper.selectByTaskId(taskId)); + } +} diff --git a/src/main/java/com/cisd/tms/modules/init/service/InitService.java b/src/main/java/com/cisd/tms/modules/init/service/InitService.java new file mode 100644 index 0000000..663697f --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/init/service/InitService.java @@ -0,0 +1,37 @@ +package com.cisd.tms.modules.init.service; + +import com.cisd.tms.modules.init.dto.InitPlanTemplateResponse; +import com.cisd.tms.modules.init.dto.InitPreviewRequest; +import com.cisd.tms.modules.init.dto.InitPreviewResponse; +import com.cisd.tms.modules.init.repository.InitTaskRepository; +import java.util.List; +import org.springframework.stereotype.Service; + +@Service +public class InitService { + + private final InitTaskRepository initTaskRepository; + + public InitService(InitTaskRepository initTaskRepository) { + this.initTaskRepository = initTaskRepository; + } + + public InitPlanTemplateResponse loadTemplate(String version) { + InitPlanTemplateResponse response = new InitPlanTemplateResponse(); + response.setVersion(version == null || version.isBlank() ? "enterprise" : version); + response.setSupportedVersions(List.of("enterprise", "indirect", "direct-lite")); + response.setTemplatePath("classpath:/initplan/"); + return response; + } + + public InitPreviewResponse preview(InitPreviewRequest request) { + String previewTaskId = "preview-" + request.getVersion(); + boolean existed = initTaskRepository.findByTaskId(previewTaskId).isPresent(); + + InitPreviewResponse response = new InitPreviewResponse(); + response.setVersion(request.getVersion()); + response.setStepCount(request.getNodeCount() <= 0 ? 1 : request.getNodeCount()); + response.setSummary(existed ? "init preview generated from existing task" : "init preview generated"); + return response; + } +} diff --git a/src/main/java/com/cisd/tms/modules/key/package-info.java b/src/main/java/com/cisd/tms/modules/key/package-info.java new file mode 100644 index 0000000..29c7185 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/key/package-info.java @@ -0,0 +1,4 @@ +/** + * key module. + */ +package com.cisd.tms.modules.key; diff --git a/src/main/java/com/cisd/tms/modules/sign/controller/internal/InternalSignController.java b/src/main/java/com/cisd/tms/modules/sign/controller/internal/InternalSignController.java new file mode 100644 index 0000000..0bfd340 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/controller/internal/InternalSignController.java @@ -0,0 +1,37 @@ +package com.cisd.tms.modules.sign.controller.internal; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.modules.sign.dto.internal.InternalSignPreviewRequest; +import com.cisd.tms.modules.sign.dto.internal.InternalSignPreviewResponse; +import com.cisd.tms.modules.sign.service.SignService; +import com.cisd.tms.modules.sign.support.SignCommand; +import com.cisd.tms.modules.sign.support.SignResult; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/sign") +public class InternalSignController { + + private final SignService signService; + + public InternalSignController(SignService signService) { + this.signService = signService; + } + + @PostMapping("/preview") + public ApiResponse preview(@Valid @RequestBody InternalSignPreviewRequest request) { + SignCommand command = new SignCommand(); + command.setAlgorithm(request.getAlgorithm()); + command.setPlainText(request.getPlainText()); + + SignResult result = signService.sign(command); + InternalSignPreviewResponse response = new InternalSignPreviewResponse(); + response.setAlgorithm(result.getAlgorithm()); + response.setDigestHex(result.getDigestHex()); + return ApiResponse.success(response); + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/controller/openapi/OpenSignController.java b/src/main/java/com/cisd/tms/modules/sign/controller/openapi/OpenSignController.java new file mode 100644 index 0000000..3500f4f --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/controller/openapi/OpenSignController.java @@ -0,0 +1,41 @@ +package com.cisd.tms.modules.sign.controller.openapi; + +import com.cisd.tms.modules.sign.dto.openapi.OpenSignRequest; +import com.cisd.tms.modules.sign.dto.openapi.OpenSignResponse; +import com.cisd.tms.modules.sign.service.SignService; +import com.cisd.tms.modules.sign.support.SignCommand; +import com.cisd.tms.modules.sign.support.SignResult; +import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/openapi/v1/sign") +public class OpenSignController { + + private final SignService signService; + + public OpenSignController(SignService signService) { + this.signService = signService; + } + + @PostMapping("/signature") + public OpenSignResponse signature(@Valid @RequestBody OpenSignRequest request) { + SignCommand command = new SignCommand(); + command.setRequestId(request.getRequestId()); + command.setAlgorithm(request.getAlgorithm()); + command.setPlainText(request.getPayload()); + + SignResult result = signService.sign(command); + + OpenSignResponse response = new OpenSignResponse(); + response.setRequestId(result.getRequestId()); + response.setAlgorithm(result.getAlgorithm()); + response.setDigestHex(result.getDigestHex()); + response.setSignature(result.getSignature()); + response.setSignedAt(result.getSignedAt().toString()); + return response; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/dto/internal/InternalSignPreviewRequest.java b/src/main/java/com/cisd/tms/modules/sign/dto/internal/InternalSignPreviewRequest.java new file mode 100644 index 0000000..a4f2065 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/dto/internal/InternalSignPreviewRequest.java @@ -0,0 +1,27 @@ +package com.cisd.tms.modules.sign.dto.internal; + +import jakarta.validation.constraints.NotBlank; + +public class InternalSignPreviewRequest { + + @NotBlank(message = "plainText is required") + private String plainText; + + private String algorithm; + + public String getPlainText() { + return plainText; + } + + public void setPlainText(String plainText) { + this.plainText = plainText; + } + + public String getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/dto/internal/InternalSignPreviewResponse.java b/src/main/java/com/cisd/tms/modules/sign/dto/internal/InternalSignPreviewResponse.java new file mode 100644 index 0000000..4c932b8 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/dto/internal/InternalSignPreviewResponse.java @@ -0,0 +1,23 @@ +package com.cisd.tms.modules.sign.dto.internal; + +public class InternalSignPreviewResponse { + + private String algorithm; + private String digestHex; + + public String getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + public String getDigestHex() { + return digestHex; + } + + public void setDigestHex(String digestHex) { + this.digestHex = digestHex; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/dto/openapi/OpenSignRequest.java b/src/main/java/com/cisd/tms/modules/sign/dto/openapi/OpenSignRequest.java new file mode 100644 index 0000000..d18e0de --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/dto/openapi/OpenSignRequest.java @@ -0,0 +1,38 @@ +package com.cisd.tms.modules.sign.dto.openapi; + +import jakarta.validation.constraints.NotBlank; + +public class OpenSignRequest { + + @NotBlank(message = "requestId is required") + private String requestId; + + @NotBlank(message = "payload is required") + private String payload; + + private String algorithm; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getPayload() { + return payload; + } + + public void setPayload(String payload) { + this.payload = payload; + } + + public String getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/dto/openapi/OpenSignResponse.java b/src/main/java/com/cisd/tms/modules/sign/dto/openapi/OpenSignResponse.java new file mode 100644 index 0000000..14a72bb --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/dto/openapi/OpenSignResponse.java @@ -0,0 +1,50 @@ +package com.cisd.tms.modules.sign.dto.openapi; + +public class OpenSignResponse { + + private String requestId; + private String algorithm; + private String digestHex; + private String signature; + private String signedAt; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + public String getDigestHex() { + return digestHex; + } + + public void setDigestHex(String digestHex) { + this.digestHex = digestHex; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public String getSignedAt() { + return signedAt; + } + + public void setSignedAt(String signedAt) { + this.signedAt = signedAt; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/package-info.java b/src/main/java/com/cisd/tms/modules/sign/package-info.java new file mode 100644 index 0000000..f035c17 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/package-info.java @@ -0,0 +1,4 @@ +/** + * sign module. + */ +package com.cisd.tms.modules.sign; diff --git a/src/main/java/com/cisd/tms/modules/sign/service/SignService.java b/src/main/java/com/cisd/tms/modules/sign/service/SignService.java new file mode 100644 index 0000000..9c7d034 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/service/SignService.java @@ -0,0 +1,30 @@ +package com.cisd.tms.modules.sign.service; + +import com.cisd.tms.modules.sign.support.SignCommand; +import com.cisd.tms.modules.sign.support.SignProvider; +import com.cisd.tms.modules.sign.support.SignResult; +import com.cisd.tms.modules.sign.support.SignatureData; +import java.time.OffsetDateTime; +import org.springframework.stereotype.Service; + +@Service +public class SignService { + + private final SignProvider signProvider; + + public SignService(SignProvider signProvider) { + this.signProvider = signProvider; + } + + public SignResult sign(SignCommand command) { + SignatureData signatureData = signProvider.sign(command.getAlgorithm(), command.getPlainText()); + + SignResult result = new SignResult(); + result.setRequestId(command.getRequestId()); + result.setAlgorithm(signatureData.getAlgorithm()); + result.setDigestHex(signatureData.getDigestHex()); + result.setSignature(signatureData.getSignature()); + result.setSignedAt(OffsetDateTime.now()); + return result; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/support/Sha256MockSignProvider.java b/src/main/java/com/cisd/tms/modules/sign/support/Sha256MockSignProvider.java new file mode 100644 index 0000000..9bfe5c0 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/support/Sha256MockSignProvider.java @@ -0,0 +1,53 @@ +package com.cisd.tms.modules.sign.support; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import org.springframework.stereotype.Component; + +@Component +public class Sha256MockSignProvider implements SignProvider { + + private static final String DEFAULT_ALGORITHM = "SHA-256"; + + @Override + public SignatureData sign(String algorithm, String plainText) { + String normalized = normalizeAlgorithm(algorithm); + byte[] contentBytes = plainText.getBytes(StandardCharsets.UTF_8); + byte[] digest = digest(normalized, contentBytes); + String digestHex = toHex(digest); + String signature = Base64.getEncoder().encodeToString((digestHex + ":" + normalized).getBytes(StandardCharsets.UTF_8)); + return new SignatureData(normalized, digestHex, signature); + } + + private String normalizeAlgorithm(String algorithm) { + if (algorithm == null || algorithm.isBlank()) { + return DEFAULT_ALGORITHM; + } + String value = algorithm.trim().toUpperCase(); + if ("SHA256".equals(value)) { + return DEFAULT_ALGORITHM; + } + if ("SHA-256".equals(value)) { + return DEFAULT_ALGORITHM; + } + throw new IllegalArgumentException("Unsupported sign algorithm: " + algorithm); + } + + private byte[] digest(String algorithm, byte[] source) { + try { + return MessageDigest.getInstance(algorithm).digest(source); + } catch (NoSuchAlgorithmException ex) { + throw new IllegalStateException("Algorithm unavailable: " + algorithm, ex); + } + } + + private String toHex(byte[] bytes) { + StringBuilder builder = new StringBuilder(bytes.length * 2); + for (byte b : bytes) { + builder.append(String.format("%02x", b)); + } + return builder.toString(); + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/support/SignCommand.java b/src/main/java/com/cisd/tms/modules/sign/support/SignCommand.java new file mode 100644 index 0000000..445da9d --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/support/SignCommand.java @@ -0,0 +1,32 @@ +package com.cisd.tms.modules.sign.support; + +public class SignCommand { + + private String requestId; + private String algorithm; + private String plainText; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + public String getPlainText() { + return plainText; + } + + public void setPlainText(String plainText) { + this.plainText = plainText; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/support/SignProvider.java b/src/main/java/com/cisd/tms/modules/sign/support/SignProvider.java new file mode 100644 index 0000000..33d40ef --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/support/SignProvider.java @@ -0,0 +1,6 @@ +package com.cisd.tms.modules.sign.support; + +public interface SignProvider { + + SignatureData sign(String algorithm, String plainText); +} diff --git a/src/main/java/com/cisd/tms/modules/sign/support/SignResult.java b/src/main/java/com/cisd/tms/modules/sign/support/SignResult.java new file mode 100644 index 0000000..8df5e4c --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/support/SignResult.java @@ -0,0 +1,52 @@ +package com.cisd.tms.modules.sign.support; + +import java.time.OffsetDateTime; + +public class SignResult { + + private String requestId; + private String algorithm; + private String digestHex; + private String signature; + private OffsetDateTime signedAt; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getAlgorithm() { + return algorithm; + } + + public void setAlgorithm(String algorithm) { + this.algorithm = algorithm; + } + + public String getDigestHex() { + return digestHex; + } + + public void setDigestHex(String digestHex) { + this.digestHex = digestHex; + } + + public String getSignature() { + return signature; + } + + public void setSignature(String signature) { + this.signature = signature; + } + + public OffsetDateTime getSignedAt() { + return signedAt; + } + + public void setSignedAt(OffsetDateTime signedAt) { + this.signedAt = signedAt; + } +} diff --git a/src/main/java/com/cisd/tms/modules/sign/support/SignatureData.java b/src/main/java/com/cisd/tms/modules/sign/support/SignatureData.java new file mode 100644 index 0000000..e441262 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/sign/support/SignatureData.java @@ -0,0 +1,26 @@ +package com.cisd.tms.modules.sign.support; + +public class SignatureData { + + private final String algorithm; + private final String digestHex; + private final String signature; + + public SignatureData(String algorithm, String digestHex, String signature) { + this.algorithm = algorithm; + this.digestHex = digestHex; + this.signature = signature; + } + + public String getAlgorithm() { + return algorithm; + } + + public String getDigestHex() { + return digestHex; + } + + public String getSignature() { + return signature; + } +} diff --git a/src/main/java/com/cisd/tms/modules/system/controller/HealthInternalController.java b/src/main/java/com/cisd/tms/modules/system/controller/HealthInternalController.java new file mode 100644 index 0000000..b872c85 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/system/controller/HealthInternalController.java @@ -0,0 +1,21 @@ +package com.cisd.tms.modules.system.controller; + +import com.cisd.tms.common.api.ApiResponse; +import java.util.Map; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/device") +public class HealthInternalController { + + @GetMapping("/status") + public ApiResponse> status() { + return ApiResponse.success(Map.of( + "status", "UP", + "service", "tms-framework", + "message", "base framework ready" + )); + } +} diff --git a/src/main/java/com/cisd/tms/modules/system/package-info.java b/src/main/java/com/cisd/tms/modules/system/package-info.java new file mode 100644 index 0000000..0f8a0f7 --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/system/package-info.java @@ -0,0 +1,4 @@ +/** + * system module. + */ +package com.cisd.tms.modules.system; diff --git a/src/main/java/com/cisd/tms/modules/upgrade/package-info.java b/src/main/java/com/cisd/tms/modules/upgrade/package-info.java new file mode 100644 index 0000000..5adecaa --- /dev/null +++ b/src/main/java/com/cisd/tms/modules/upgrade/package-info.java @@ -0,0 +1,4 @@ +/** + * upgrade module. + */ +package com.cisd.tms.modules.upgrade; diff --git a/src/main/java/com/cisd/tms/security/internal/InternalApiAuthInterceptor.java b/src/main/java/com/cisd/tms/security/internal/InternalApiAuthInterceptor.java new file mode 100644 index 0000000..58d0179 --- /dev/null +++ b/src/main/java/com/cisd/tms/security/internal/InternalApiAuthInterceptor.java @@ -0,0 +1,49 @@ +package com.cisd.tms.security.internal; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.common.config.properties.TmsSecurityProperties; +import com.cisd.tms.common.enums.ErrorCode; +import com.cisd.tms.common.util.HttpResponseUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Objects; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class InternalApiAuthInterceptor implements HandlerInterceptor { + + private static final String TOKEN_HEADER = "X-Internal-Token"; + + private final TmsSecurityProperties securityProperties; + private final ObjectMapper objectMapper; + + public InternalApiAuthInterceptor(TmsSecurityProperties securityProperties, ObjectMapper objectMapper) { + this.securityProperties = securityProperties; + this.objectMapper = objectMapper; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String expectedToken = securityProperties.getInternalToken(); + String actualToken = request.getHeader(TOKEN_HEADER); + + if (Objects.equals(expectedToken, actualToken)) { + return true; + } + + writeUnauthorized(response, "internal token invalid"); + return false; + } + + private void writeUnauthorized(HttpServletResponse response, String message) throws IOException { + HttpResponseUtil.writeJson( + response, + HttpServletResponse.SC_UNAUTHORIZED, + ApiResponse.fail(ErrorCode.UNAUTHORIZED.getCode(), message), + objectMapper + ); + } +} diff --git a/src/main/java/com/cisd/tms/security/internal/package-info.java b/src/main/java/com/cisd/tms/security/internal/package-info.java new file mode 100644 index 0000000..8d256b1 --- /dev/null +++ b/src/main/java/com/cisd/tms/security/internal/package-info.java @@ -0,0 +1,4 @@ +/** + * Internal API security components. + */ +package com.cisd.tms.security.internal; diff --git a/src/main/java/com/cisd/tms/security/openapi/OpenApiReplayGuard.java b/src/main/java/com/cisd/tms/security/openapi/OpenApiReplayGuard.java new file mode 100644 index 0000000..8c9ec95 --- /dev/null +++ b/src/main/java/com/cisd/tms/security/openapi/OpenApiReplayGuard.java @@ -0,0 +1,40 @@ +package com.cisd.tms.security.openapi; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import org.springframework.stereotype.Component; + +@Component +public class OpenApiReplayGuard { + + private final Map nonceExpireSeconds = new ConcurrentHashMap<>(); + private final AtomicLong cleanupCounter = new AtomicLong(0); + + public boolean tryAcquire(String appId, String nonce, long nowSeconds, long ttlSeconds) { + if (ttlSeconds <= 0) { + ttlSeconds = 300; + } + + String key = appId + ":" + nonce; + long expiry = nowSeconds + ttlSeconds; + AtomicBoolean accepted = new AtomicBoolean(false); + + nonceExpireSeconds.compute(key, (k, existingExpiry) -> { + if (existingExpiry == null || existingExpiry < nowSeconds) { + accepted.set(true); + return expiry; + } + accepted.set(false); + return existingExpiry; + }); + + // Opportunistic cleanup to keep memory growth under control. + if (cleanupCounter.incrementAndGet() % 1000 == 0) { + nonceExpireSeconds.entrySet().removeIf(e -> e.getValue() < nowSeconds); + } + + return accepted.get(); + } +} diff --git a/src/main/java/com/cisd/tms/security/openapi/OpenApiSignAuthInterceptor.java b/src/main/java/com/cisd/tms/security/openapi/OpenApiSignAuthInterceptor.java new file mode 100644 index 0000000..927bb3f --- /dev/null +++ b/src/main/java/com/cisd/tms/security/openapi/OpenApiSignAuthInterceptor.java @@ -0,0 +1,115 @@ +package com.cisd.tms.security.openapi; + +import com.cisd.tms.common.api.ApiResponse; +import com.cisd.tms.common.config.properties.TmsSecurityProperties; +import com.cisd.tms.common.enums.ErrorCode; +import com.cisd.tms.common.util.HmacUtil; +import com.cisd.tms.common.util.HttpResponseUtil; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.time.Instant; +import java.util.Map; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class OpenApiSignAuthInterceptor implements HandlerInterceptor { + + private static final String APP_ID_HEADER = "X-App-Id"; + private static final String TIMESTAMP_HEADER = "X-Timestamp"; + private static final String NONCE_HEADER = "X-Nonce"; + private static final String SIGNATURE_HEADER = "X-Signature"; + + private final TmsSecurityProperties securityProperties; + private final OpenApiReplayGuard replayGuard; + private final ObjectMapper objectMapper; + + public OpenApiSignAuthInterceptor( + TmsSecurityProperties securityProperties, + OpenApiReplayGuard replayGuard, + ObjectMapper objectMapper + ) { + this.securityProperties = securityProperties; + this.replayGuard = replayGuard; + this.objectMapper = objectMapper; + } + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String appId = trimHeader(request, APP_ID_HEADER); + String timestamp = trimHeader(request, TIMESTAMP_HEADER); + String nonce = trimHeader(request, NONCE_HEADER); + String signature = trimHeader(request, SIGNATURE_HEADER); + + if (isBlank(appId) || isBlank(timestamp) || isBlank(nonce) || isBlank(signature)) { + writeUnauthorized(response, "missing openapi auth headers"); + return false; + } + + Map clients = securityProperties.getOpenapi().getClients(); + String appSecret = clients.get(appId); + if (isBlank(appSecret)) { + writeUnauthorized(response, "unknown app id"); + return false; + } + + long requestEpoch; + try { + requestEpoch = Long.parseLong(timestamp); + } catch (NumberFormatException ex) { + writeUnauthorized(response, "invalid timestamp"); + return false; + } + + long now = Instant.now().getEpochSecond(); + long skew = securityProperties.getOpenapi().getTimestampSkewSeconds(); + if (Math.abs(now - requestEpoch) > skew) { + writeUnauthorized(response, "timestamp expired"); + return false; + } + + if (!replayGuard.tryAcquire(appId, nonce, now, skew * 2)) { + writeUnauthorized(response, "replayed nonce"); + return false; + } + + String content = appId + "\n" + timestamp + "\n" + nonce; + String expected = HmacUtil.hmacSha256Hex(appSecret, content); + + if (!secureEquals(expected, signature.toLowerCase())) { + writeUnauthorized(response, "signature invalid"); + return false; + } + + return true; + } + + private boolean secureEquals(String expected, String actual) { + return MessageDigest.isEqual( + expected.getBytes(StandardCharsets.UTF_8), + actual.getBytes(StandardCharsets.UTF_8) + ); + } + + private String trimHeader(HttpServletRequest request, String name) { + String value = request.getHeader(name); + return value == null ? null : value.trim(); + } + + private boolean isBlank(String value) { + return value == null || value.isBlank(); + } + + private void writeUnauthorized(HttpServletResponse response, String message) throws IOException { + HttpResponseUtil.writeJson( + response, + HttpServletResponse.SC_UNAUTHORIZED, + ApiResponse.fail(ErrorCode.UNAUTHORIZED.getCode(), message), + objectMapper + ); + } +} diff --git a/src/main/java/com/cisd/tms/security/openapi/package-info.java b/src/main/java/com/cisd/tms/security/openapi/package-info.java new file mode 100644 index 0000000..e410108 --- /dev/null +++ b/src/main/java/com/cisd/tms/security/openapi/package-info.java @@ -0,0 +1,4 @@ +/** + * OpenAPI signature authentication components. + */ +package com.cisd.tms.security.openapi; diff --git a/src/main/java/com/cisd/tms/security/package-info.java b/src/main/java/com/cisd/tms/security/package-info.java new file mode 100644 index 0000000..64cf35a --- /dev/null +++ b/src/main/java/com/cisd/tms/security/package-info.java @@ -0,0 +1,4 @@ +/** + * Cross-cutting security components. + */ +package com.cisd.tms.security; diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml new file mode 100644 index 0000000..2965f14 --- /dev/null +++ b/src/main/resources/application-dev.yml @@ -0,0 +1,22 @@ +spring: + datasource: + url: jdbc:mysql://127.0.0.1:4000/tms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: root + driver-class-name: com.mysql.cj.jdbc.Driver + +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + global-config: + db-config: + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + configuration: + map-underscore-to-camel-case: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + +logging: + level: + com.cisd.tms: info + com.baomidou.mybatisplus: info diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..19b4ab1 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,21 @@ +spring: + datasource: + url: jdbc:mysql://tidb-host:4000/tms?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai + username: ${TMS_DB_USER:root} + password: ${TMS_DB_PASSWORD:change-me} + driver-class-name: com.mysql.cj.jdbc.Driver + +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + global-config: + db-config: + logic-delete-field: deleted + logic-delete-value: 1 + logic-not-delete-value: 0 + configuration: + map-underscore-to-camel-case: true + +logging: + level: + com.cisd.tms: info + root: info diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..2997788 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,40 @@ +spring: + application: + name: tms-framework + profiles: + active: dev + +server: + port: 8080 + +management: + endpoints: + web: + exposure: + include: health,info,metrics + endpoint: + health: + show-details: always + +springdoc: + api-docs: + enabled: true + path: /v3/api-docs + swagger-ui: + enabled: true + path: /swagger-ui.html + tags-sorter: alpha + operations-sorter: alpha + +tms: + security: + internal-token: ${TMS_INTERNAL_TOKEN:change-me-internal-token} + openapi: + timestamp-skew-seconds: 300 + clients: + demo-app: ${TMS_OPENAPI_DEMO_SECRET:change-me-openapi-secret} + crypto-card: + enabled: ${TMS_CRYPTO_CARD_ENABLED:false} + mode: ${TMS_CRYPTO_CARD_MODE:MOCK} + vendor-lib-path: ${TMS_CRYPTO_VENDOR_LIB_PATH:} + vendor-lib-name: ${TMS_CRYPTO_VENDOR_LIB_NAME:swsdsdf} diff --git a/src/main/resources/db/migration/V1__init_auth_device_tables.sql b/src/main/resources/db/migration/V1__init_auth_device_tables.sql new file mode 100644 index 0000000..baafc6f --- /dev/null +++ b/src/main/resources/db/migration/V1__init_auth_device_tables.sql @@ -0,0 +1,29 @@ +CREATE TABLE IF NOT EXISTS tms_init_task ( + id BIGINT PRIMARY KEY, + task_id VARCHAR(64) NOT NULL, + version VARCHAR(32) NOT NULL, + status VARCHAR(32) NOT NULL, + create_time DATETIME(3) NOT NULL, + update_time DATETIME(3) NOT NULL, + UNIQUE KEY uk_tms_init_task_task_id (task_id) +); + +CREATE TABLE IF NOT EXISTS tms_auth_user ( + id BIGINT PRIMARY KEY, + username VARCHAR(64) NOT NULL, + display_name VARCHAR(128) NOT NULL, + role VARCHAR(64) NOT NULL, + create_time DATETIME(3) NOT NULL, + update_time DATETIME(3) NOT NULL, + UNIQUE KEY uk_tms_auth_user_username (username) +); + +CREATE TABLE IF NOT EXISTS tms_device_node ( + id BIGINT PRIMARY KEY, + node_id VARCHAR(64) NOT NULL, + host VARCHAR(128) NOT NULL, + status VARCHAR(32) NOT NULL, + create_time DATETIME(3) NOT NULL, + update_time DATETIME(3) NOT NULL, + UNIQUE KEY uk_tms_device_node_node_id (node_id) +); diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..2276512 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,15 @@ + + + + + + + ${PATTERN} + UTF-8 + + + + + + + diff --git a/src/main/resources/mapper/auth/AuthUserMapper.xml b/src/main/resources/mapper/auth/AuthUserMapper.xml new file mode 100644 index 0000000..b57d9dc --- /dev/null +++ b/src/main/resources/mapper/auth/AuthUserMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/device/DeviceNodeMapper.xml b/src/main/resources/mapper/device/DeviceNodeMapper.xml new file mode 100644 index 0000000..2aa5b5b --- /dev/null +++ b/src/main/resources/mapper/device/DeviceNodeMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/init/InitTaskMapper.xml b/src/main/resources/mapper/init/InitTaskMapper.xml new file mode 100644 index 0000000..85351ba --- /dev/null +++ b/src/main/resources/mapper/init/InitTaskMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/src/test/java/com/cisd/tms/TmsApplicationTests.java b/src/test/java/com/cisd/tms/TmsApplicationTests.java new file mode 100644 index 0000000..0760680 --- /dev/null +++ b/src/test/java/com/cisd/tms/TmsApplicationTests.java @@ -0,0 +1,12 @@ +package com.cisd.tms; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class TmsApplicationTests { + + @Test + void contextLoads() { + } +} diff --git a/src/test/java/com/cisd/tms/integration/crypto/pcie/service/MockPcieCryptoServiceExtendedTest.java b/src/test/java/com/cisd/tms/integration/crypto/pcie/service/MockPcieCryptoServiceExtendedTest.java new file mode 100644 index 0000000..422563e --- /dev/null +++ b/src/test/java/com/cisd/tms/integration/crypto/pcie/service/MockPcieCryptoServiceExtendedTest.java @@ -0,0 +1,201 @@ +package com.cisd.tms.integration.crypto.pcie.service; + +import com.cisd.tms.integration.crypto.pcie.model.BackupDataResult; +import com.cisd.tms.integration.crypto.pcie.model.EccExternalSignRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ExchangeDigitEnvelopeRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardEccKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateStandardRsaKeyPairRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateAgreementDataAndKeyEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.AgreementDataAndKeyEccResult; +import com.cisd.tms.integration.crypto.pcie.model.StandardKeyPairResult; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyRequest; +import com.cisd.tms.integration.crypto.pcie.model.EccAgreementSessionKeyResult; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithEpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.GenerateKeyWithIpkRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskEccRequest; +import com.cisd.tms.integration.crypto.pcie.model.ImportKeyWithIskRsaRequest; +import com.cisd.tms.integration.crypto.pcie.model.RsaExternalPrivateKeyOpRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class MockPcieCryptoServiceExtendedTest { + + private final MockPcieCryptoService service = new MockPcieCryptoService(); + + @Test + void shouldGenerateSessionKeyWithIpkRsa() { + GenerateKeyWithIpkRsaRequest request = new GenerateKeyWithIpkRsaRequest(); + request.setIpkIndex(1); + request.setKeyBits(128); + request.setOutBufferSize(64); + + BackupDataResult result = service.generateKeyWithIpkRsa(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 64); + } + + @Test + void shouldGenerateSessionKeyWithEpkRsa() { + GenerateKeyWithEpkRsaRequest request = new GenerateKeyWithEpkRsaRequest(); + request.setKeyBits(128); + request.setPublicKeyBlob(new byte[] {1, 2, 3}); + request.setOutBufferSize(64); + + BackupDataResult result = service.generateKeyWithEpkRsa(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 64); + } + + @Test + void shouldImportSessionKeyWithIskRsa() { + ImportKeyWithIskRsaRequest request = new ImportKeyWithIskRsaRequest(); + request.setIskIndex(2); + request.setWrappedKey(new byte[] {1, 2, 3, 4}); + + service.importKeyWithIskRsa(request); + } + + @Test + void shouldDoExternalPrivateOpRsa() { + RsaExternalPrivateKeyOpRequest request = new RsaExternalPrivateKeyOpRequest(); + request.setPrivateKeyBlob(new byte[] {1, 2, 3}); + request.setInput(new byte[] {4, 5}); + request.setOutBufferSize(32); + + BackupDataResult result = service.rsaExternalPrivateKeyOperation(request); + Assertions.assertEquals(32, result.getLength()); + } + + @Test + void shouldDoExternalSignEcc() { + EccExternalSignRequest request = new EccExternalSignRequest(); + request.setAlgId(1); + request.setPrivateKeyBlob(new byte[] {1, 2, 3}); + request.setData(new byte[] {4, 5}); + request.setSignatureBufferSize(64); + + BackupDataResult result = service.eccExternalSign(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 64); + } + + @Test + void shouldGenerateSessionKeyWithIpkEcc() { + GenerateKeyWithIpkEccRequest request = new GenerateKeyWithIpkEccRequest(); + request.setIpkIndex(1); + request.setKeyBits(128); + request.setOutBufferSize(96); + + BackupDataResult result = service.generateKeyWithIpkEcc(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 96); + } + + @Test + void shouldGenerateSessionKeyWithEpkEcc() { + GenerateKeyWithEpkEccRequest request = new GenerateKeyWithEpkEccRequest(); + request.setKeyBits(128); + request.setAlgId(1); + request.setPublicKeyBlob(new byte[] {1, 2, 3}); + request.setOutBufferSize(96); + + BackupDataResult result = service.generateKeyWithEpkEcc(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 96); + } + + @Test + void shouldImportSessionKeyWithIskEcc() { + ImportKeyWithIskEccRequest request = new ImportKeyWithIskEccRequest(); + request.setIskIndex(3); + request.setEncryptedKeyBlob(new byte[] {1, 2, 3, 4}); + + service.importKeyWithIskEcc(request); + } + + @Test + void shouldExchangeDigitEnvelopeBaseOnRsa() { + ExchangeDigitEnvelopeRsaRequest request = new ExchangeDigitEnvelopeRsaRequest(); + request.setKeyIndex(2); + request.setPublicKeyBlob(new byte[] {1, 2, 3}); + request.setInputEnvelopeBlob(new byte[] {4, 5, 6}); + request.setOutBufferSize(128); + + BackupDataResult result = service.exchangeDigitEnvelopeBaseOnRsa(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 128); + } + + @Test + void shouldGenerateStandardRsaKeyPair() { + GenerateStandardRsaKeyPairRequest request = new GenerateStandardRsaKeyPairRequest(); + request.setKeyBits(2048); + request.setPublicKeyBufferSize(512); + request.setPrivateKeyBufferSize(2048); + + StandardKeyPairResult result = service.generateStandardRsaKeyPair(request); + Assertions.assertTrue(result.getPublicKeyLength() > 0 && result.getPublicKeyLength() <= 512); + Assertions.assertTrue(result.getPrivateKeyLength() > 0 && result.getPrivateKeyLength() <= 2048); + } + + @Test + void shouldGenerateStandardEccKeyPair() { + GenerateStandardEccKeyPairRequest request = new GenerateStandardEccKeyPairRequest(); + request.setAlgId(1); + request.setKeyBits(256); + request.setPublicKeyBufferSize(256); + request.setPrivateKeyBufferSize(256); + + StandardKeyPairResult result = service.generateStandardEccKeyPair(request); + Assertions.assertTrue(result.getPublicKeyLength() > 0 && result.getPublicKeyLength() <= 256); + Assertions.assertTrue(result.getPrivateKeyLength() > 0 && result.getPrivateKeyLength() <= 256); + } + + @Test + void shouldExchangeDigitEnvelopeBaseOnEcc() { + ExchangeDigitEnvelopeEccRequest request = new ExchangeDigitEnvelopeEccRequest(); + request.setKeyIndex(1); + request.setAlgId(1); + request.setPublicKeyBlob(new byte[] {1, 2, 3}); + request.setInputEnvelopeBlob(new byte[] {4, 5, 6}); + request.setOutBufferSize(256); + + BackupDataResult result = service.exchangeDigitEnvelopeBaseOnEcc(request); + Assertions.assertTrue(result.getLength() > 0 && result.getLength() <= 256); + } + + @Test + void shouldGenerateAgreementDataAndKeyWithEcc() { + GenerateAgreementDataAndKeyEccRequest request = new GenerateAgreementDataAndKeyEccRequest(); + request.setIskIndex(1); + request.setKeyBits(128); + request.setResponseId(new byte[] {1, 1, 1}); + request.setSponsorId(new byte[] {2, 2, 2}); + request.setSponsorPublicKeyBlob(new byte[] {3, 3, 3}); + request.setSponsorTmpPublicKeyBlob(new byte[] {4, 4, 4}); + request.setResponsePublicKeyBufferSize(128); + request.setResponseTmpPublicKeyBufferSize(128); + + AgreementDataAndKeyEccResult result = service.generateAgreementDataAndKeyWithEcc(request); + Assertions.assertTrue(result.getResponsePublicKeyLength() > 0 && result.getResponsePublicKeyLength() <= 128); + Assertions.assertTrue(result.getResponseTmpPublicKeyLength() > 0 && result.getResponseTmpPublicKeyLength() <= 128); + Assertions.assertTrue(result.isSessionKeyGenerated()); + } + + @Test + void shouldGenerateSessionKeyWithEccAgreementFlow() { + EccAgreementSessionKeyRequest request = new EccAgreementSessionKeyRequest(); + request.setIskIndex(1); + request.setKeyBits(128); + request.setSponsorId(new byte[] {1, 2, 3}); + request.setResponseId(new byte[] {4, 5, 6}); + request.setResponsePublicKeyBlob(new byte[] {7, 8, 9}); + request.setResponseTmpPublicKeyBlob(new byte[] {10, 11, 12}); + request.setSponsorPublicKeyBufferSize(128); + request.setSponsorTmpPublicKeyBufferSize(128); + request.setSessionKeyBufferSize(64); + + EccAgreementSessionKeyResult result = service.generateSessionKeyWithEccAgreement(request); + Assertions.assertTrue(result.getSponsorPublicKeyLength() > 0 && result.getSponsorPublicKeyLength() <= 128); + Assertions.assertTrue(result.getSponsorTmpPublicKeyLength() > 0 && result.getSponsorTmpPublicKeyLength() <= 128); + Assertions.assertTrue(result.getSessionKeyLength() > 0 && result.getSessionKeyLength() <= 64); + Assertions.assertTrue(result.isSessionKeyGenerated()); + } +}