{"record":{"id":"47e74a4bb4bc99a9","repo":"commaai/openpilot","slug":"authenticateserver-rejected-by-euicc-auth-server","errorCode":null,"errorMessage":"AuthenticateServer rejected by eUICC: {AUTH_SERVER_ERROR_CODES.get(code, 'unknown')} (0x{code:02X})","messagePattern":"AuthenticateServer rejected by eUICC: (.+?) \\(0x(.+?)\\)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"openpilot/common/esim/lpa.py","lineNumber":489,"sourceCode":"  challenge_resp = es10x_command(client, encode_tlv(TAG_EUICC_CHALLENGE, b\"\"))\n  challenge = require_tag(require_tag(challenge_resp, TAG_EUICC_CHALLENGE, \"GetEuiccDataResponse\"),\n                          TAG_STATUS, \"challenge in response\")\n  info_resp = es10x_command(client, encode_tlv(TAG_EUICC_INFO, b\"\"))\n  require_tag(info_resp, TAG_EUICC_INFO, \"GetEuiccInfo1Response\")\n  return challenge, info_resp\n\n\ndef authenticate_server(client: AtClient, b64_signed1: str, b64_sig1: str, b64_pk_id: str, b64_cert: str, matching_id: str) -> str:\n  tac = bytes([0x35, 0x29, 0x06, 0x11])\n  device_info = encode_tlv(TAG_STATUS, tac) + encode_tlv(0xA1, b\"\")\n  ctx_inner = encode_tlv(TAG_STATUS, matching_id.encode(\"utf-8\")) + encode_tlv(0xA1, device_info)\n  content = b64d(b64_signed1) + b64d(b64_sig1) + b64d(b64_pk_id) + b64d(b64_cert) + encode_tlv(0xA0, ctx_inner)\n  response = es10x_command(client, encode_tlv(TAG_AUTH_SERVER, content))\n  root = require_tag(response, TAG_AUTH_SERVER, \"AuthenticateServerResponse\")\n  error_tag = find_tag(root, 0xA1)\n  if error_tag is not None:\n    code = int.from_bytes(error_tag, \"big\") if error_tag else 0\n    raise RuntimeError(f\"AuthenticateServer rejected by eUICC: {AUTH_SERVER_ERROR_CODES.get(code, 'unknown')} (0x{code:02X})\")\n  return b64e(response)\n\n\ndef prepare_download(client: AtClient, b64_signed2: str, b64_sig2: str, b64_cert: str, cc: str | None = None) -> str:\n  smdp_signed2 = b64d(b64_signed2)\n  smdp_signature2 = b64d(b64_sig2)\n  smdp_certificate = b64d(b64_cert)\n  smdp_signed2_root = find_tag(smdp_signed2, 0x30)\n  if smdp_signed2_root is None:\n    raise RuntimeError(\"Invalid smdpSigned2\")\n  transaction_id = find_tag(smdp_signed2_root, TAG_STATUS)\n  cc_required_flag = find_tag(smdp_signed2_root, 0x01)\n  if transaction_id is None or cc_required_flag is None:\n    raise RuntimeError(\"Invalid smdpSigned2\")\n  content = smdp_signed2 + smdp_signature2\n  if int.from_bytes(cc_required_flag, \"big\") != 0:\n    if not cc:\n      raise RuntimeError(\"Confirmation code required but not provided\")","sourceCodeStart":471,"sourceCodeEnd":507,"githubUrl":"https://github.com/commaai/openpilot/blob/516ec1e68203439a73f340f1d0b3b91eabc626ee/openpilot/common/esim/lpa.py#L471-L507","documentation":"authenticate_server() sends the ES10b AuthenticateServer command (SM-DP+ signed data, signature, cert) to the eUICC. If the response contains tag 0xA1 instead of a success payload, the eUICC refused authentication and the integer code is mapped through AUTH_SERVER_ERROR_CODES (e.g. 0x05 invalidServerSignature, 0x0A matchingIdRefused, 0x10 insufficientMemory); unmapped codes print 'unknown'.","triggerScenarios":"During profile download when the eUICC rejects the SM-DP+: server signature invalid (0x05), eUICC certificate expired/revoked (0x02/0x03), matching ID from the QR refused (0x0A), eUICC GSMA CI public key unknown (0x06), or insufficient eUICC memory (0x10).","commonSituations":"QR code whose matchingId doesn't match the reserved profile (wrong QR / already consumed elsewhere); carrier server certificate/signature issues; test eUICCs with expired certificates; eUICC memory full from many installed profiles.","solutions":["Map the hex code: 0x01 eUICC verification failed, 0x02/0x03 eUICC cert expired/revoked (hardware issue, replace eSIM), 0x05 invalid server signature (server/carrier problem), 0x0A matchingId refused (wrong or used QR), 0x10 insufficient memory (delete profiles)","For 0x0A: request a fresh QR code; the current one is bound to another session/device","For 0x10: delete unused profiles to free eUICC memory, then retry download","For 0x05/0x06: retry later or escalate to the carrier; also verify device clock is correct (cert validation is time-sensitive)"],"exampleFix":"# before\nb64_auth = authenticate_server(client, s1, sig1, pkid, cert, matching_id)\n# RuntimeError: AuthenticateServer rejected by eUICC: matchingIdRefused (0x0A)\n\n# after\nfrom openpilot.common.esim.lpa import authenticate_server\n\ntry:\n  b64_auth = authenticate_server(client, s1, sig1, pkid, cert, matching_id)\nexcept RuntimeError as e:\n  if '(0x0A)' in str(e):\n    raise SystemExit('QR code matching ID refused; get a new QR code from carrier') from e\n  if '(0x10)' in str(e):\n    raise SystemExit('eUICC memory full; delete profiles and retry') from e\n  raise","handlingStrategy":"try-catch","validationCode":"from openpilot.common.esim.lpa import list_profiles\n\n# pre-flight: free memory for 0x10, valid QR for 0x0A\nif len(list_profiles(client)) >= max_profiles_supported:\n  raise SystemExit('eUICC near memory limit; delete profiles before download')","typeGuard":null,"tryCatchPattern":"try:\n  b64_auth = authenticate_server(client, s1, sig1, pkid, cert, matching_id)\nexcept RuntimeError as e:\n  code = str(e).rsplit('0x', 1)[-1]\n  if code == '0A':\n    raise SystemExit('QR matching ID refused; obtain fresh QR') from e\n  if code == '10':\n    raise SystemExit('eUICC memory full; delete profiles') from e\n  if code in ('02', '03'):\n    raise SystemExit('eUICC certificate issue; hardware replacement needed') from e\n  raise","preventionTips":["Use each QR activation code exactly once and keep the matching ID intact","Check eUICC free memory before downloads on devices with many profiles","Ensure system time is valid — certificate validation depends on it"],"tags":["esim","euicc","authentication","sgp22","download","python"],"backgroundTag":null,"analyzedSha":"516ec1e68203439a73f340f1d0b3b91eabc626ee","analyzedAt":"2026-08-15T00:17:37.461Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}