Security Access를 붙이다 보면 계산 로직보다 먼저 순서에서 막히는 경우가 있다.
- seed 요청은 나간다
- seed 응답도 잘 받는다
- key도 보낸다
- 그런데 unlock 직후나 다음 요청에서
7F xx 24가 뜬다
이때 key 알고리즘부터 의심하기 쉽다.
그런데 실제로는 seed/key 순서와 세션 문맥이 중간에 어긋난 경우가 더 자주 보인다.
오늘 메모는 DoIP에서 NRC 0x24 Request Sequence Error를 볼 때 먼저 확인할 순서다.
0x24는 순서가 틀렸다는 신호에 가깝다
0x24는 흔히 이렇게 읽는다.
요청 자체를 모르는 건 아닌데, 지금 이 상태에서 그 요청이 올 차례는 아니다.
즉 이 코드는 보통 아래 둘과 다르다.
0x35나0x36처럼 key 값이나 횟수 정책이 틀린 경우- timeout처럼 아예 응답이 없는 경우
그래서 0x24가 뜨면 계산식보다 먼저
이 요청이 같은 unlock 흐름 위에 올라가 있는지를 봐야 한다.
Security Access는 요청 두 개만 맞으면 끝나지 않는다
겉으로는 단순하다.
seed request
-> seed response
-> key request
-> unlock success
그런데 실무에서는 이 흐름 사이에 같이 유지돼야 하는 것이 더 있다.
- 같은 진단 세션인지
- 같은 ECU 문맥인지
- 같은 SA/TA 조합인지
- 재연결이나 reset이 없었는지
- 중간에 다른 요청이 끼지 않았는지
즉 seed와 key만 연달아 보지 말고
같은 연결 세대의 같은 transaction 흐름인지를 같이 확인해야 한다.
자주 터지는 패턴 1: seed 받고 다른 문맥에서 key를 보낸다
이게 제일 흔하다.
예를 들면 이런 식이다.
SecurityAccess requestSeed
-> seed 응답 수신
-> TCP 재연결 또는 RA 재수행
-> 이전 seed로 key 전송
-> NRC 0x24
테스터 로그에는 “방금 seed 받았는데 왜 안 되지?”처럼 보이지만,
ECU 입장에서는 이전 연결 문맥의 seed일 수 있다.
DoIP에서는 특히 아래 이벤트가 끼면 순서가 무효화되기 쉽다.
- TCP 소켓 재연결
- Routing Activation 재수행
- ECU Reset
- DiagnosticSessionControl 재진입
이후에는 seed를 다시 받아야 하는 경우가 많다.
자주 터지는 패턴 2: seed/key 사이에 다른 요청이 끼어든다
멀티 스레드 테스터에서 많이 본다.
task A: requestSeed
task B: DID read
task A: sendKey
-> NRC 0x24
애플리케이션 입장에서는 DID read 하나쯤 괜찮아 보일 수 있다.
하지만 ECU 구현에 따라서는 Security Access를 짧은 순차 흐름으로 기대한다.
특히 아래 요청이 사이에 들어가면 더 헷갈린다.
- 다른 SecurityAccess level 요청
- 세션 전환 요청
- RoutineControl
- 기능 주소 기반 요청
이 경우 네트워크보다 먼저
동일 ECU 대상 요청 직렬화를 의심하는 편이 빠르다.
자주 터지는 패턴 3: requestSeed를 두 번 보내고 마지막 seed를 안 쓴다
자동 재시도 코드가 있으면 이런 실수도 나온다.
requestSeed #1
-> seed A
requestSeed #2
-> seed B
sendKey(key from seed A)
-> NRC 0x24 또는 unlock 실패
로그를 길게 보면 분명 seed는 받았는데,
실제로 key 계산에 쓴 값이 마지막 seed가 아닌 경우가 있다.
특히 아래 조건에서 잘 숨는다.
- seed 응답을 전역 버퍼에 덮어씀
- 로그에는 마지막 seed만 남음
- key 계산은 비동기 작업이라 이전 값을 참조
이때 0x24는 계산 오류처럼 보이기보다
요청 시퀀스 관리가 흐트러졌다는 힌트로 보는 게 낫다.
자주 터지는 패턴 4: unlock 뒤 세션이 바뀌었는데 그대로 다음 요청을 보낸다
어떤 ECU는 unlock 성공 직후에도
다음 요청이 특정 세션 위에서만 유효하다.
예를 들면:
- extended session에서 unlock해야 함
- programming session 전환 뒤에만 특정 서비스 허용
- reset 이후 unlock 상태 초기화
이때 unlock 응답만 보고 곧바로 다음 서비스를 보내면
실패 코드가 0x24로 보이기도 한다.
즉 Security Access 디버깅은
key 성공 여부 하나보다 unlock 이후 세션 문맥 유지를 같이 봐야 한다.
로그를 이렇게 남기면 빨라진다
0x24는 패킷 한 줄만 보면 잘 안 풀린다.
나는 보통 아래 항목을 붙여 본다.
- SecurityAccess sub-function과 level
- seed 수신 시각과 seed 식별값 일부
- key 전송 시각과 그 사이에 낀 다른 요청
- 소켓 재연결, Routing Activation, 세션 전환 이벤트
- unlock 이후 첫 후속 요청의 서비스 ID
이 다섯 줄이 있으면
“알고리즘이 틀린가”보다
“같은 흐름 위에서 key를 보냈는가”가 먼저 보인다.
구현 쪽에서 무난한 패턴
실무에서는 아래처럼 묶어두는 편이 덜 꼬인다.
requestSeed
-> seed 저장
-> 같은 ECU/세션/연결 세대에서만 sendKey 허용
-> unlock 성공 전까지 다른 충돌 요청 직렬화
-> 재연결/세션 변경/reset 발생 시 seed 문맥 폐기
핵심은 seed를 단순 바이트 배열이 아니라
세션에 종속된 상태값으로 보는 것이다.
가능하면 연결 컨텍스트에 이런 값을 같이 두는 편이 좋다.
- security level pending
- seed generation
- socket generation
- current diagnostic session
- security unlock valid
빠른 체크리스트
requestSeed와sendKey사이에 재연결이나 RA 재수행이 없는지 확인- 중간에 다른 UDS 요청이 끼어들지 않도록 같은 ECU 요청을 직렬화했는지 확인
- 자동 재시도로 seed를 두 번 받아 놓고 이전 seed로 key를 계산하지 않는지 확인
- unlock 이후 필요한 세션 전환 순서를 코드에 명시했는지 확인
0x24를 단순 key 계산 실패로 뭉개지 않고 시퀀스 오류로 분리 기록하는지 확인
한 줄 요약
DoIP에서 Security Access 뒤 NRC 0x24가 뜨면 key 알고리즘보다 먼저 seed/key 사이에 연결, 세션, 병렬 요청이 끼어 같은 unlock 문맥이 깨졌는지 확인하는 편이 빠르다.
추천 키워드
DoIP, UDS, Security Access, NRC, Request Sequence Error, Session Control
DevBJ | 오늘을살자, Log Today