מזהי המכשיר

ב-Android 10, ההרשאות למזהי מכשירים השתנו כך שכל מזהי המכשירים מוגנים עכשיו על ידי ההרשאה READ_PRIVILEGED_PHONE_STATE. לפני Android 10, מזהי מכשירים קבועים (IMEI/MEID,‏ IMSI,‏ SIM והמספר הסידורי של ה-Build) היו מוגנים מאחורי הרשאת זמן הריצה READ_PHONE_STATE. ההרשאה READ_PRIVILEGED_PHONE_STATE ניתנת רק לאפליקציות שחתומות באמצעות מפתח הפלטפורמה ולאפליקציות מערכת עם הרשאות מיוחדות.

מידע נוסף על דרישות ההרשאה החדשות זמין בדפי Javadoc‏ TelephonyManager.java ו-Build.java.

השינוי הזה משפיע על ממשקי ה-API הבאים:

  • TelephonyManager#getDeviceId
  • TelephonyManager#getImei
  • TelephonyManager#getMeid
  • TelephonyManager#getSimSerialNumber
  • TelephonyManager#getSubscriberId
  • Build#getSerial

גישה לאפליקציות של ספקי סלולר ללא ההרשאה READ_PRIVILEGED_PHONE_STATE

אפליקציות של ספקי סלולר שנטענות מראש ולא עומדות בדרישות של ההרשאה READ_PRIVILEGED_PHONE_STATE יכולות ליישם אחת מהאפשרויות שבטבלה שלמטה.

אפשרות תיאור מגבלות
הרשאות של ספק ב-UICC פלטפורמת Android טוענת אישורים שמאוחסנים ב-UICC ומעניקה הרשאה לאפליקציות שנחתמו על ידי האישורים האלה לבצע קריאות לשיטות מיוחדות. לספקי סלולר מדור קודם יש אוכלוסייה גדולה של כרטיסי SIM, שלא ניתן לעדכן בקלות. בנוסף, ספקים שאין להם זכויות כתיבה לכרטיסי SIM חדשים (לדוגמה, MVNO שכרטיסי ה-SIM שלהם הונפקו על ידי MNO) לא יכולים להוסיף או לעדכן אישורים בכרטיסי ה-SIM.
הוספה לרשימת ההיתרים של OEM יצרני ציוד מקורי יכולים להשתמש ב-OP_READ_DEVICE_IDENTIFIER כדי לספק מזהי מכשירים לאפליקציות של ספקים שנכללות ברשימת ההיתרים. הפתרון הזה לא ניתן להרחבה לכל הספקים.
קוד הקצאת סוג (TAC) משתמשים בשיטה getTypeAllocationCode שהושקה ב-Android 10 כדי לחשוף את ה-TAC שמחזיר את פרטי היצרן והדגם. המידע ב-TAC לא מספיק כדי לזהות מכשיר ספציפי.
מערך למספור מספרי הטלפון (MSISDN) ספקים יכולים להשתמש במספר הטלפון (MSISDN), שזמין בקטע TelephonyManager עם קבוצת ההרשאות PHONE, כדי לחפש את מספר ה-IMEI במערכות העורפיות שלהם. הדרישה הזו מחייבת השקעה משמעותית מצד הספקים. ספקים שממפים את מפתחות הרשת שלהם באמצעות IMSI נדרשים להקצות משאבים טכניים משמעותיים כדי לעבור ל-MSISDN.

כל האפליקציות של הספק יכולות לגשת למזהי המכשיר אחרי עדכון הקובץ CarrierConfig.xml עם גיבוב אישור החתימה של האפליקציה של הספק. כשהאפליקציה של הספק קוראת לשיטה כדי לקרוא מידע עם הרשאות מיוחדות, הפלטפורמה מחפשת התאמה בין גיבוב אישור החתימה של האפליקציה (חתימת SHA-1 או SHA-256 של האישור) לבין הקובץ CarrierConfig.xml. אם נמצאת התאמה, המידע המבוקש מוחזר. אם לא נמצאה התאמה, מוחזר חריג אבטחה.

כדי להטמיע את הפתרון הזה, חברות התקשורת צריכות לבצע את השלבים הבאים:

  1. מעדכנים את CarrierConfig.xml עם הגיבוב של אישור החתימה של אפליקציית הספק ושולחים תיקון.
  2. מבקשים מיצרני הציוד המקורי לעדכן את ה-build שלהם לגרסה QPR1+ (מומלץ) או לכלול בו את תיקוני הפלטפורמה הנדרשים ואת התיקון שמכיל את הקובץ CarrierConfig.xml המעודכן משלב 1 שלמעלה.

הטמעה

צריך לעדכן את רשימת ההיתרים של הרשאות מיוחדות כדי להעניק את ההרשאה READ_PRIVILEGED_PHONE_STATE לאפליקציות מיוחדות שנדרשת להן גישה למזהי מכשירים.

מידע נוסף על הוספה לרשימת ההיתרים זמין במאמר הוספה לרשימת ההיתרים של הרשאות מיוחדות.

כדי להפעיל את ממשקי ה-API המושפעים, אפליקציה צריכה לעמוד באחת מהדרישות הבאות:

  • אם האפליקציה היא אפליקציה מובנית עם הרשאות מיוחדות, היא צריכה את ההרשאה READ_PRIVILEGED_PHONE_STATE שמוצהרת בקובץ AndroidManifest.xml. בנוסף, צריך להוסיף את ההרשאה המיוחדת הזו לרשימת ההיתרים של האפליקציה.
  • אפליקציות שמופצות דרך Google Play צריכות הרשאות של ספק הסלולר. מידע נוסף על הענקת הרשאות לחברות תובלה זמין בדף UICC Carrier Privileges.
  • אפליקציה של בעלי מכשיר או פרופיל שקיבלה את ההרשאה READ_PHONE_STATE.

אם האפליקציה לא עומדת באף אחת מהדרישות האלה, היא תפעל באופן הבא:

  • אם האפליקציה מיועדת לגרסאות קודמות ל-Q ולא ניתנה לה הרשאת הגישה READ_PHONE_STATE, מופעלת SecurityException. זהו אופן הפעולה הנוכחי בגרסאות קודמות ל-Q, כי ההרשאה הזו נדרשת כדי להפעיל את ממשקי ה-API האלה.
  • אם האפליקציה מיועדת לגרסאות שלפני Q וניתנה לה הרשאת READ_PHONE_STATE, היא מקבלת ערך null לכל ממשקי ה-API של TelephonyManager וערך Build.UNKNOWN לשיטה Build#getSerial.
  • אם האפליקציה מטרגטת ל-Android מגרסה 10 ואילך ולא עומדת באף אחת מהדרישות החדשות, היא מקבלת SecurityException.

אימות ובדיקה

חבילת בדיקות התאימות (CTS) כוללת בדיקות לאימות התנהגות הגישה הצפויה למזהי מכשירים עבור אפליקציות עם הרשאות של ספק, בעלי מכשירים ופרופילים, ואפליקציות שלא אמורות להיות להן גישה למזהי מכשירים.

הבדיקות הבאות ב-CTS ספציפיות לתכונה הזו.

cts-tradefed run cts -m CtsCarrierApiTestCases -t
    android.carrierapi.cts.CarrierApiTest

cts-tradefed run cts -m CtsTelephonyTestCases -t
    android.telephony.cts.TelephonyManagerTest

cts-tradefed run cts -m CtsTelephony3TestCases

cts-tradefed run cts -m CtsPermissionTestCases -t
    android.permission.cts.TelephonyManagerPermissionTest

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCanGetDeviceIdentifiers

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCanGetDeviceIdentifiers

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.ManagedProfileTest#testProfileOwnerCannotGetDeviceIdentifiersWithoutPermission

cts-tradefed run cts -m CtsDevicePolicyManagerTestCases -t
    com.android.cts.devicepolicy.DeviceOwnerTest#testDeviceOwnerCannotGetDeviceIdentifiersWithoutPermission

שאלות נפוצות

כמה אפליקציות אפשר להוסיף לרשימת ההיתרים ב-CarrierConfig.xml עבור (MCC, ‏ MNC) נתון?

אין הגבלה על מספר הגיבובים של האישורים שכלולים במערך.

באילו פרמטרים של CarrierConfig ב-CarrierConfig.xml צריך להשתמש כדי שאפליקציה תופיע ברשימת ההיתרים?

משתמשים בפריט ההגדרה הבא ברמה העליונה בתוך CarrierConfig.xml הספציפי מבין האפשרויות של AOSP שאתם מגדירים:

<string-array name="carrier_certificate_string_array" num="2">
    <item value="BF02262E5EF59FDD53E57059082F1A7914F284B"/>
    <item value="9F3868A3E1DD19A5311D511A60CF94D975A344B"/>
</string-array>

האם יש תבנית בסיסית של CarrierConfig שאפשר להשתמש בה?

משתמשים בתבנית הבאה. צריך להוסיף את המאפיין הזה להנכס הרלוונטי.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<carrier_config>
    <string-array name="carrier_certificate_string_array"
num="1">
        <item value="CERTIFICATE_HASH_HERE"/>
    </string-array>
</carrier_config>

האם כרטיס ה-SIM של הספק צריך להיות במכשיר כדי לגשת למזהי המכשיר?

כרטיס ה-SIM שבו משתמשים נקבע לפי כרטיס ה-SIM שמוכנס כרגע.CarrierConfig.xml כלומר, אם האפליקציה של ספק X מנסה לקבל הרשאות גישה בזמן שכרטיס ה-SIM של ספק Y מוכנס, המכשיר לא ימצא התאמה לגיבוב ויחזיר חריגת אבטחה.

במכשירים עם כמה כרטיסי SIM, לספק מספר 1 יש הרשאות גישה רק לכרטיס SIM מספר 1, ולהפך.

איך ספקי סלולר ממירים את אישור החתימה של אפליקציה לגיבוב (hash)?

כדי להמיר אישורי חתימה לגיבוב לפני שמוסיפים אותם ל-CarrierConfig.xml, מבצעים את הפעולות הבאות:

  1. ממירים את החתימה של אישור החתימה למערך בייטים באמצעות toByteArray.
  2. משתמשים ב- MessageDigest כדי להמיר את מערך הבייטים לגיבוב בסוג byte[].
  3. ממירים את הגיבוב מ-byte[] לפורמט מחרוזת הקסדצימלית. לדוגמה, אפשר לעיין בIccUtils.java.

    List<String> certHashes = new ArrayList<>();
    PackageInfo pInfo; // Carrier app PackageInfo
    MessageDigest md =
    MessageDigest.getInstance("SHA-256");
    for (Signature signature : pInfo.signatures) {
        certHashes.add(bytesToHexString(md.digest(signature.toByteArray()));
    }
  4. אם certHashes הוא מערך בגודל 2 עם ערך של 12345 ו-54321, מוסיפים את השורות הבאות לקובץ הגדרות הספק.

    <string-array name="carrier_certificate_string_array" num="2">
        <item value="12345"/>
        <item value="54321"/>
    </string-array>