Skip to content

Commit e527a44

Browse files
committed
fix can multi addr issue
1 parent 7c00f0e commit e527a44

File tree

10 files changed

+560
-61
lines changed

10 files changed

+560
-61
lines changed
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { DiagResponse, output } from 'ECB'
22

3+
let requestAddrName: string | undefined
4+
35
Util.On('Tester_eth_1.*.send', async (req) => {
6+
requestAddrName = req.getUdsAddress()?.ethAddr?.name
47
console.log('Received DOIP Diag request', req.getUdsAddress().ethAddr?.name)
58
req.testerName = 'Tester_can_0'
6-
await req.outputDiag('SIMULATE_1', req.getUdsAddress().ethAddr?.name)
9+
await req.outputDiag('SIMULATE_1', requestAddrName)
710
})
811
Util.On('Tester_can_0.*.recv', async (resp) => {
9-
console.log('Received CANTP Diag response', resp.getUdsAddress().canAddr?.name)
12+
console.log('Received CANTP Diag response')
1013
resp.testerName = 'Tester_eth_1'
11-
await resp.outputDiag('SIMULATE_0', resp.getUdsAddress().ethAddr?.name)
14+
await resp.outputDiag('SIMULATE_0', requestAddrName)
1215
})

resources/examples/uds_0x29/ecu.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,19 @@ Util.On('Tester_can_0.authenticationConfiguration.send', async (req) => {
1515
resp.diagSetParameter('returnValue', 0x2) //ACPE
1616
await resp.outputDiag()
1717
})
18+
let memorySize: number
19+
Util.On('Tester_can_0.RequestDownload520.send', async (req) => {
20+
const resp = DiagResponse.fromDiagRequest(req)
21+
memorySize = Number(req.diagGetParameter('memorySize'))
22+
console.log(`memorySize:${memorySize}`)
23+
resp.diagSetRaw(Buffer.from([0x74, 0x40, 0, 0, 0, 0x81]))
24+
await resp.outputDiag()
25+
})
26+
const ecdh = crypto.createECDH('prime256v1')
27+
ecdh.generateKeys()
28+
const publicKeyGen = ecdh.getPublicKey()
1829

30+
let challengeTester: Buffer
1931
Util.On('Tester_can_0.verifyCertificateUnidirectional.send', async (req) => {
2032
const resp = DiagResponse.fromDiagRequest(req)
2133

@@ -33,17 +45,28 @@ Util.On('Tester_can_0.verifyCertificateUnidirectional.send', async (req) => {
3345
const verifyResult = cert.verify(ca.publicKey)
3446
console.log(`verify result:${verifyResult}`)
3547
if (verifyResult) {
48+
const cLen = data.readUint16BE(5 + lengthOfCertificateClient)
49+
console.log(`challenge length:${cLen}`)
50+
//challenge
51+
challengeTester = data.subarray(
52+
7 + lengthOfCertificateClient,
53+
7 + lengthOfCertificateClient + cLen
54+
)
55+
3656
//client cert verify ok
3757
// resp.diagSetParameter('lengthOfChallengeServer',32)
3858
// resp.diagSetParameterSize('challengeServer',32*8)
3959
resp.diagSetParameterRaw('challengeServer', challenge)
4060
resp.diagSetParameter('returnValue', 0x11) //certificate ok, verify ownership
61+
62+
resp.diagSetParameterRaw('ephemeralPublicKeyServer', publicKeyGen)
63+
resp.diagSetParameter('lengthOfEphemeralPublicKeyServer', publicKeyGen.length)
4164
await resp.outputDiag()
4265
} else {
4366
throw new Error('client cert verify failed')
4467
}
4568
})
46-
69+
let realKey: Buffer
4770
Util.On('Tester_can_0.proofOfOwnership.send', async (req) => {
4871
const resp = DiagResponse.fromDiagRequest(req)
4972
const data = req.diagGetRaw()
@@ -56,9 +79,53 @@ Util.On('Tester_can_0.proofOfOwnership.send', async (req) => {
5679
const verifyResult = crypto.verify('RSA-SHA256', challenge, publicKey, sign)
5780
console.log(`verify result:${verifyResult}`)
5881
if (verifyResult) {
82+
const lengthOfEphemeralPublicKeyClient = data.readUint16BE(4 + lengthOfProofOfOwnershipClient)
83+
console.log(`ephemeralPublicKeyClient length:${lengthOfEphemeralPublicKeyClient}`)
84+
//ephemeralPublicKeyClient
85+
const ephemeralPublicKeyClient = data.subarray(
86+
6 + lengthOfProofOfOwnershipClient,
87+
6 + lengthOfProofOfOwnershipClient + lengthOfEphemeralPublicKeyClient
88+
)
89+
const sharedSecret = ecdh.computeSecret(ephemeralPublicKeyClient)
90+
91+
console.log(`sharedSecret in ecu:${sharedSecret.toString('hex')}`)
92+
93+
//hkdf
94+
const salt = Buffer.concat([challengeTester, challenge])
95+
realKey = Buffer.from(crypto.hkdfSync('sha256', sharedSecret, salt, '', 32))
96+
console.log(`realKey in ecu:${realKey.toString('hex')}`)
5997
resp.diagSetParameter('returnValue', 0x12) //authentication ok
6098
await resp.outputDiag()
6199
} else {
62100
throw new Error('client sign verify failed')
63101
}
64102
})
103+
let fwContent: Buffer = Buffer.alloc(0)
104+
let decipher: crypto.DecipherGCM
105+
106+
Util.On('Tester_can_0.TransferData540.send', async (req) => {
107+
const raw = req.diagGetRaw()
108+
if (!decipher) {
109+
decipher = crypto.createDecipheriv('aes-256-gcm', realKey, Buffer.alloc(12, 0))
110+
}
111+
const transferRequestParameterRecord = raw.subarray(2)
112+
const decrypted = decipher.update(transferRequestParameterRecord)
113+
if (fwContent.length < memorySize) {
114+
fwContent = Buffer.concat([fwContent, decrypted])
115+
if (fwContent.length >= memorySize) {
116+
console.log(`decrypted content :${fwContent.subarray(0, memorySize).toString('ascii')}`)
117+
}
118+
}
119+
const resp = DiagResponse.fromDiagRequest(req)
120+
resp.diagSetRaw(Buffer.from([0x76, Number(req.diagGetParameter('blockSequenceCounter'))]))
121+
await resp.outputDiag()
122+
})
123+
124+
Util.On('Tester_can_0.RequestTransferExit550.send', async (req) => {
125+
const raw = req.diagGetRaw()
126+
decipher.setAuthTag(raw.subarray(2))
127+
decipher.final()
128+
const resp = DiagResponse.fromDiagRequest(req)
129+
resp.diagSetRaw(Buffer.from([0x77]))
130+
await resp.outputDiag()
131+
})

resources/examples/uds_0x29/test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

resources/examples/uds_0x29/tester.ts

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import fs from 'fs/promises'
33
import path from 'path'
44
import crypto from 'crypto'
55

6-
const challenge = Buffer.from(
6+
const challengeSelf = Buffer.from(
77
Array(32)
88
.fill(0)
99
.map(() => Math.floor(Math.random() * 256))
1010
)
11+
let fwContent: Buffer
1112
Util.Init(async () => {
1213
// reader client.crt
1314
const cert = await fs.readFile(path.join(process.env.PROJECT_ROOT, 'client.crt'), 'utf-8')
@@ -25,11 +26,23 @@ Util.Init(async () => {
2526
//random challenge 32 bytes
2627
verifyCertificateUnidirectional.diagSetParameter('lengthOfChallengeClient', 32)
2728
verifyCertificateUnidirectional.diagSetParameterSize('challengeClient', 32 * 8)
28-
verifyCertificateUnidirectional.diagSetParameterRaw('challengeClient', challenge)
29+
verifyCertificateUnidirectional.diagSetParameterRaw('challengeClient', challengeSelf)
2930
//save
3031
await verifyCertificateUnidirectional.changeService()
32+
33+
//read fwContent
34+
fwContent = await fs.readFile(path.join(process.env.PROJECT_ROOT, 'test.txt'))
35+
//setup 0x34 size
36+
const RequestDownload520 = DiagRequest.from('Tester_can_0.RequestDownload520')
37+
RequestDownload520.diagSetParameter('memorySize', fwContent.length)
38+
await RequestDownload520.changeService()
3139
})
3240

41+
const ecdh = crypto.createECDH('prime256v1')
42+
ecdh.generateKeys()
43+
const publicKey = ecdh.getPublicKey()
44+
let realKey: Buffer
45+
3346
Util.On('Tester_can_0.verifyCertificateUnidirectional.recv', async (resp) => {
3447
const data = resp.diagGetRaw()
3548
// 69 11 11 lengthOfCertificateClient(2)
@@ -47,6 +60,80 @@ Util.On('Tester_can_0.verifyCertificateUnidirectional.recv', async (resp) => {
4760
proofOfOwnership.diagSetParameterSize('proofOfOwnershipClient', sign.length * 8)
4861
proofOfOwnership.diagSetParameterRaw('proofOfOwnershipClient', sign)
4962
proofOfOwnership.diagSetParameter('lengthOfProofOfOwnershipClient', sign.length)
63+
64+
proofOfOwnership.diagSetParameter('lengthOfEphemeralPublicKeyClient', publicKey.length)
65+
proofOfOwnership.diagSetParameterSize('ephemeralPublicKeyClient', publicKey.length * 8)
66+
proofOfOwnership.diagSetParameterRaw('ephemeralPublicKeyClient', publicKey)
5067
//save
5168
await proofOfOwnership.changeService()
69+
70+
const lengthOfPeerKey = data.readUint16BE(5 + lengthOfCertificateClient)
71+
const peerPublicKey = data.subarray(
72+
5 + lengthOfCertificateClient + 2,
73+
5 + lengthOfCertificateClient + 2 + lengthOfPeerKey
74+
)
75+
console.log(`peerPublicKey length:${lengthOfPeerKey}`)
76+
const sharedSecret = ecdh.computeSecret(peerPublicKey)
77+
console.log(`sharedSecret in tester:${sharedSecret.toString('hex')}`)
78+
//hkdf
79+
const salt = Buffer.concat([challengeSelf, challenge])
80+
realKey = Buffer.from(crypto.hkdfSync('sha256', sharedSecret, salt, '', 32))
81+
console.log(`realKey in tester:${realKey.toString('hex')}`)
82+
})
83+
84+
let maxChunkSize = 0
85+
Util.On('Tester_can_0.RequestDownload520.recv', (resp) => {
86+
maxChunkSize = resp.diagGetParameterRaw('maxNumberOfBlockLength').readUint32BE(0)
87+
})
88+
89+
//aes-gcm encrypt
90+
91+
Util.Register('Tester_can_0.SecureDownload', async () => {
92+
if (maxChunkSize <= 2) {
93+
throw new Error('maxNumberOfBlockLength is undefined or too small')
94+
}
95+
if (fwContent) {
96+
const cipher = crypto.createCipheriv('aes-256-gcm', realKey, Buffer.alloc(12, 0))
97+
maxChunkSize -= 2
98+
if (maxChunkSize & 0x07) {
99+
maxChunkSize -= maxChunkSize & 0x07
100+
}
101+
const numChunks = Math.ceil(fwContent.length / maxChunkSize)
102+
const list = []
103+
for (let i = 0; i < numChunks; i++) {
104+
const start = i * maxChunkSize
105+
const end = Math.min(start + maxChunkSize, fwContent.length)
106+
console.log(`chunk ${i + 1}/${numChunks} start: ${start}, end: ${end}`)
107+
const chunk = fwContent.subarray(start, end)
108+
109+
const transferRequest = DiagRequest.from('Tester_can_0.TransferData540')
110+
111+
const encrypt = cipher.update(chunk)
112+
console.log(
113+
`chunk ${i + 1}/${numChunks} size: ${chunk.length}, encrypted size: ${encrypt.length}`
114+
)
115+
transferRequest.diagSetParameterSize('transferRequestParameterRecord', encrypt.length * 8)
116+
// 设置传输请求参数记录
117+
transferRequest.diagSetParameterRaw('transferRequestParameterRecord', encrypt)
118+
119+
// 计算块序号 (从1开始)
120+
const blockSequenceCounter = Buffer.alloc(1)
121+
blockSequenceCounter.writeUInt8((i + 1) & 0xff) // 使用循环计数 1-255
122+
transferRequest.diagSetParameterRaw('blockSequenceCounter', blockSequenceCounter)
123+
124+
list.push(transferRequest)
125+
}
126+
//set auth tag
127+
cipher.final()
128+
const authTag = cipher.getAuthTag()
129+
const RequestTransferExit550 = DiagRequest.from('Tester_can_0.RequestTransferExit550')
130+
RequestTransferExit550.diagSetParameterSize('auth', authTag.length * 8)
131+
// 设置传输请求参数记录
132+
RequestTransferExit550.diagSetParameterRaw('auth', authTag)
133+
await RequestTransferExit550.changeService()
134+
// 发送所有块
135+
return list
136+
} else {
137+
return []
138+
}
52139
})

0 commit comments

Comments
 (0)