מזהי המכשיר

ב-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. ‫Update CarrierConfig.xml עם הגיבוב של אישור החתימה של אפליקציית הספק ושולחים תיקון.
  2. מבקשים מיצרני ה-OEM לעדכן את הגרסה שלהם ל-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>