SFP 이미지에서 vendor name과 PN을 수정한 뒤 어느 EEPROM 체크섬을 재계산해야 하나
벤치 작업: 고객 장비가 기대하는 벤더 문자열과 파트넘버를 달게 하려고 SFP+ 모듈 소량 배치를 리코딩하는 중입니다. 수정 자체는 헥스 에디터로 하면 사소한 일이고, 쓰기는 통과되고, 다시 읽으면 제가 쓴 것과 바이트 단위로 일치하는데 - 그런데도 호스트가 여전히 모듈을 튕겨냅니다.
- 일반 SFP+ 모듈, A0 페이지를 수작업으로 수정
- 딸려온 도구를 쓰는 CH341 기반 프로그래머
- 수정한 필드: vendor name과 vendor part number, 그 외에는 안 건드림
- 안 건드린 덤프를 같은 모듈에 그대로 써넣으면 정상 동작 - 그러니 쓰기 경로 자체는 문제가 아님
수정 후 비교해본 것:
edited fields : vendor name, vendor PN
byte 63 CC_BASE : identical to the original image
byte 95 CC_EXT : identical to the original image
host : rejects the module, checksum error
그러니까 payload는 바뀌었는데 합계 바이트는 분명히 안 움직인 겁니다. 직접 툴을 짜기 전에 여쭤봅니다 - 이 두 체크섬이 실제로 커버하는 바이트 범위가 어디인가요, 단순 덧셈 합인가요 아니면 CRC 비슷한 건가요, 그리고 모듈마다 손으로 계산하지 않아도 되게 이걸 재계산해주는 관리되고 있는 유틸리티가 있나요?
Comments 4
여러분의 프로그래머는 CH341 기반 도구가 보통 하는 일을 하고 있는 겁니다 - 즉 아무것도 안 하는 거죠. 건네준 바이트를 그대로 쓰고 체크섬 필드는 절대 안 건드립니다. 벤더 프로그래머는 쓰기 시 재계산을 해주는데, 그것만 써본 사람들이 이 문제를 절대 안 겪고 이 주제 전체가 상상 속 얘기라고 확신하는 이유가 그겁니다.
툴을 짜기 전에 짚어볼 게 두 가지 있습니다. 첫째, 쓰기 후 이미지를 다시 읽은 게 뭔가요 - 쓴 도구 그대로인가요, 아니면 독립된 다른 걸로요? 자기 캐시를 보여주는 리더는 칩에 실제로 안 들어간 바이트도 태연하게 보여줍니다. 둘째, 수정된 이미지의 0번부터 62번 바이트까지 합을 직접 계산해서 63번 바이트와 비교하신 건가요, 아니면 63번 바이트를 원본 덤프와만 비교하신 건가요? '안 바뀜'과 '맞음'은 같은 테스트가 아닌데, 남기신 내용은 첫 번째 것만 보여줍니다.
거부하는 호스트가 뭔지도 밝혀둘 만합니다. 어떤 건 identity 필드만 읽고 아무것도 검증 안 하고, 어떤 건 엄격하게 검증해서 합이 어긋나는 순간 모듈을 떨굽니다. 같은 이미지라도 판정이 다릅니다.
이건 두 개고, 둘 다 CRC 없이 그냥 8비트 덧셈 합입니다.
vendor name과 vendor PN 둘 다 base 영역에 있어서, 수정하신 게 CC_BASE는 무효로 만들고 CC_EXT는 정당하게 맞는 채로 남긴 겁니다. serial number와 date code 수정은 대신 extended 범위를 건드리고, 그러면 이번엔 95번 바이트가 낡은 값이 됩니다. 둘 중 뭐든 재계산은 버퍼 위에서 두 줄이면 됩니다 - 범위를 합산하고, 0xFF로 마스킹하고, 합 바이트에 저장하면 끝입니다.
손으로 하고 싶지 않으시다면 도구가 있습니다. py-sfp-eeprom은 Python에서 EEPROM 이미지를 만들고 검증하고(
python3 -m sfp_eeprom),sfppi는 Raspberry Pi에서 돌면서 합을 확인하고 고쳐주겠다고 제안합니다. 둘 중 뭐든 헥스 에디터에 암산 조합보다 나은 습관입니다. 실패 양상이 조용하거든요 - 모듈은 쓴 그대로 정확히 다시 읽히고 불평하는 건 호스트뿐입니다.MSA 체크섬 두 개를 제대로 맞추는 건 필요조건이고, 어느 포트에 꽂느냐에 따라 충분조건은 아닙니다.
Cisco가 흔히 보는 예입니다 - identity 체크가 문자열만 보는 게 아닙니다. 몇 년 전 누군가가, Cisco 코딩 모듈이 갖는 값이 vendor code 바이트에 이어 name 바이트를 먹인
xxd -r -p | md5sum정도의 평범한 방법으로 재현된다는 걸 알아냈습니다. 그 덤프들 안에서는 code와 name이 서로 묶여 있습니다 - Finisar는 02 뒤에, Methode는 0E 뒤에 있는 식이죠. 이 둘이 어긋나면 Catalyst 2960X는 unlock 명령을 걸었든 안 걸었든 모듈을 다시 뱉어냅니다.동작하던 모듈에서 복사한 덤프가 다른 벤더 문자열을 붙여넣은 순간 안 되기 시작하는 게 보통 이 이유 때문입니다. 체크섬은 멀쩡한데 identity가 더 이상 자기 일관성이 없는 거죠.
"체크섬 두 개만 고치면 끝"이라는 틀에 작은 정정을 하나 하자면, 이건 MSA 필드에는 맞는 말이지, 모든 벤더가 생각하는 유효한 이미지 기준에 다 맞는 건 아닙니다.
HP가 꾸준한 반례입니다. J4858B 이미지에서 시리얼 넘버(68~83번 바이트)를 수정하면 A0의 124~127번 바이트도 같이 바뀝니다 - MSA의 CC_BASE와 CC_EXT 바이트를 넘어선 자리에 있는 벤더 체크섬이죠. 이건 예전에 길게 논의됐는데 아무도 알고리즘을 공개한 적이 없습니다. 사람들은 그 바이트가 중요하다는 것만 확인했고 스레드는 거기서 끝났습니다. J4859C와 J9150A 주변에서도 같은 얘기가 보고됐습니다. 이후 HP와 Aruba 장비는 challenge-response 방식(HPIDv2)으로 넘어갔는데, 이건 EEPROM 안에서는 아예 위조할 수가 없습니다.
그러니 도구에 투자하기 전에, 목표 호스트가 뭘 검증하는지부터 파악하세요 - 평범한 호스트라면 덧셈 합 두 개, Catalyst라면 자체 일관된 identity, 그리고 일부 HP 부품에서는 여러분이 재현할 수 없는 비공개 필드까지요.