DoIP에서 Security Access 뒤 NRC 0x24가 뜬다: seed/key 이후 요청 순서와 세션 문맥을 같이 봐야 한다
DoIP에서 Security Access 자체는 되는 것 같은데 unlock 직후 요청이 NRC 0x24 Request Sequence Error로 실패하면, key 계산보다 먼저 seed/key 순서와 세션 문맥이 유지됐는지 봐야 한다. 재연결, 세션 전환, 병렬 요청이 끼면 같은 ECU라도 이전 unlock 흐름이 쉽게 무효화된다.
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