Loading cmds/pm/src/com/android/commands/pm/Pm.java +131 −4 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ package com.android.commands.pm; import com.android.internal.content.PackageHelper; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; Loading @@ -40,17 +43,20 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import com.android.internal.content.PackageHelper; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.InvalidAlgorithmParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.WeakHashMap; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public final class Pm { IPackageManager mPm; Loading Loading @@ -763,6 +769,15 @@ public final class Pm { String installerPackageName = null; String opt; String algo = null; byte[] iv = null; byte[] key = null; String macAlgo = null; byte[] macKey = null; byte[] tag = null; while ((opt=nextOption()) != null) { if (opt.equals("-l")) { installFlags |= PackageManager.INSTALL_FORWARD_LOCK; Loading @@ -783,6 +798,48 @@ public final class Pm { } else if (opt.equals("-f")) { // Override if -s option is specified. installFlags |= PackageManager.INSTALL_INTERNAL; } else if (opt.equals("--algo")) { algo = nextOptionData(); if (algo == null) { System.err.println("Error: must supply argument for --algo"); showUsage(); return; } } else if (opt.equals("--iv")) { iv = hexToBytes(nextOptionData()); if (iv == null) { System.err.println("Error: must supply argument for --iv"); showUsage(); return; } } else if (opt.equals("--key")) { key = hexToBytes(nextOptionData()); if (key == null) { System.err.println("Error: must supply argument for --key"); showUsage(); return; } } else if (opt.equals("--macalgo")) { macAlgo = nextOptionData(); if (macAlgo == null) { System.err.println("Error: must supply argument for --macalgo"); showUsage(); return; } } else if (opt.equals("--mackey")) { macKey = hexToBytes(nextOptionData()); if (macKey == null) { System.err.println("Error: must supply argument for --mackey"); showUsage(); return; } } else if (opt.equals("--tag")) { tag = hexToBytes(nextOptionData()); if (tag == null) { System.err.println("Error: must supply argument for --tag"); showUsage(); return; } } else { System.err.println("Error: Unknown option: " + opt); showUsage(); Loading @@ -790,6 +847,44 @@ public final class Pm { } } final ContainerEncryptionParams encryptionParams; if (algo != null || iv != null || key != null || macAlgo != null || macKey != null || tag != null) { if (algo == null || iv == null || key == null) { System.err.println("Error: all of --algo, --iv, and --key must be specified"); showUsage(); return; } if (macAlgo != null || macKey != null || tag != null) { if (macAlgo == null || macKey == null || tag == null) { System.err.println("Error: all of --macalgo, --mackey, and --tag must " + "be specified"); showUsage(); return; } } try { final SecretKey encKey = new SecretKeySpec(key, "RAW"); final SecretKey macSecretKey; if (macKey == null || macKey.length == 0) { macSecretKey = null; } else { macSecretKey = new SecretKeySpec(macKey, "RAW"); } encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv), encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); return; } } else { encryptionParams = null; } final Uri apkURI; final Uri verificationURI; Loading @@ -816,7 +911,7 @@ public final class Pm { PackageInstallObserver obs = new PackageInstallObserver(); try { mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName, verificationURI, null); verificationURI, null, encryptionParams); synchronized (obs) { while (!obs.finished) { Loading @@ -839,6 +934,37 @@ public final class Pm { } } /** * Convert a string containing hex-encoded bytes to a byte array. * * @param input String containing hex-encoded bytes * @return input as an array of bytes */ private byte[] hexToBytes(String input) { if (input == null) { return null; } final int inputLength = input.length(); if ((inputLength % 2) != 0) { System.err.print("Invalid length; must be multiple of 2"); return null; } final int byteLength = inputLength / 2; final byte[] output = new byte[byteLength]; int inputIndex = 0; int byteIndex = 0; while (inputIndex < inputLength) { output[byteIndex++] = (byte) Integer.parseInt( input.substring(inputIndex, inputIndex + 2), 16); inputIndex += 2; } return output; } public void runCreateUser() { // Need to be run as root if (Process.myUid() != ROOT_UID) { Loading Loading @@ -1236,7 +1362,8 @@ public final class Pm { System.err.println(" pm list libraries"); System.err.println(" pm list users"); System.err.println(" pm path PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); System.err.println(" pm clear PACKAGE"); System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); Loading core/java/android/app/ApplicationPackageManager.java +3 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; Loading Loading @@ -973,10 +974,10 @@ final class ApplicationPackageManager extends PackageManager { @Override public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) { ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) { try { mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName, verificationURI, manifestDigest); verificationURI, manifestDigest, encryptionParams); } catch (RemoteException e) { // Should never happen! } Loading core/java/android/content/pm/ContainerEncryptionParams.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * Copyright 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; parcelable ContainerEncryptionParams; core/java/android/content/pm/ContainerEncryptionParams.java 0 → 100644 +378 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Slog; import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; /** * Represents encryption parameters used to read a container. * * @hide */ public class ContainerEncryptionParams implements Parcelable { protected static final String TAG = "ContainerEncryptionParams"; /** What we print out first when toString() is called. */ private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{"; /** * Parameter type for parceling that indicates the next parameters are * IvParameters. */ private static final int ENC_PARAMS_IV_PARAMETERS = 1; /** Parameter type for paceling that indicates there are no MAC parameters. */ private static final int MAC_PARAMS_NONE = 1; /** The encryption algorithm used. */ private final String mEncryptionAlgorithm; /** The parameter spec to be used for encryption. */ private final IvParameterSpec mEncryptionSpec; /** Secret key to be used for decryption. */ private final SecretKey mEncryptionKey; /** Algorithm name for the MAC to be used. */ private final String mMacAlgorithm; /** The parameter spec to be used for the MAC tag authentication. */ private final AlgorithmParameterSpec mMacSpec; /** Secret key to be used for MAC tag authentication. */ private final SecretKey mMacKey; /** MAC tag authenticating the data in the container. */ private final byte[] mMacTag; /** Offset into file where authenticated (e.g., MAC protected) data begins. */ private final int mAuthenticatedDataStart; /** Offset into file where encrypted data begins. */ private final int mEncryptedDataStart; /** * Offset into file for the end of encrypted data (and, by extension, * authenticated data) in file. */ private final int mDataEnd; public ContainerEncryptionParams(String encryptionAlgorithm, AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey) throws InvalidAlgorithmParameterException { this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1, -1); } /** * Creates container encryption specifications for installing from encrypted * containers. * * @param encryptionAlgorithm encryption algorithm to use; format matches * JCE * @param encryptionSpec algorithm parameter specification * @param encryptionKey key used for decryption * @param macAlgorithm MAC algorithm to use; format matches JCE * @param macSpec algorithm parameters specification, may be {@code null} * @param macKey key used for authentication (i.e., for the MAC tag) * @param authenticatedDataStart offset of start of authenticated data in * stream * @param encryptedDataStart offset of start of encrypted data in stream * @param dataEnd offset of the end of both the authenticated and encrypted * data * @throws InvalidAlgorithmParameterException */ public ContainerEncryptionParams(String encryptionAlgorithm, AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm, AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag, int authenticatedDataStart, int encryptedDataStart, int dataEnd) throws InvalidAlgorithmParameterException { if (TextUtils.isEmpty(encryptionAlgorithm)) { throw new NullPointerException("algorithm == null"); } else if (encryptionSpec == null) { throw new NullPointerException("encryptionSpec == null"); } else if (encryptionKey == null) { throw new NullPointerException("encryptionKey == null"); } if (!TextUtils.isEmpty(macAlgorithm)) { if (macKey == null) { throw new NullPointerException("macKey == null"); } } if (!(encryptionSpec instanceof IvParameterSpec)) { throw new InvalidAlgorithmParameterException( "Unknown parameter spec class; must be IvParameters"); } mEncryptionAlgorithm = encryptionAlgorithm; mEncryptionSpec = (IvParameterSpec) encryptionSpec; mEncryptionKey = encryptionKey; mMacAlgorithm = macAlgorithm; mMacSpec = macSpec; mMacKey = macKey; mMacTag = macTag; mAuthenticatedDataStart = authenticatedDataStart; mEncryptedDataStart = encryptedDataStart; mDataEnd = dataEnd; } public String getEncryptionAlgorithm() { return mEncryptionAlgorithm; } public AlgorithmParameterSpec getEncryptionSpec() { return mEncryptionSpec; } public SecretKey getEncryptionKey() { return mEncryptionKey; } public String getMacAlgorithm() { return mMacAlgorithm; } public AlgorithmParameterSpec getMacSpec() { return mMacSpec; } public SecretKey getMacKey() { return mMacKey; } public byte[] getMacTag() { return mMacTag; } public int getAuthenticatedDataStart() { return mAuthenticatedDataStart; } public int getEncryptedDataStart() { return mEncryptedDataStart; } public int getDataEnd() { return mDataEnd; } @Override public int describeContents() { return 0; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ContainerEncryptionParams)) { return false; } final ContainerEncryptionParams other = (ContainerEncryptionParams) o; // Primitive comparison if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart) || (mEncryptedDataStart != other.mEncryptedDataStart) || (mDataEnd != other.mDataEnd)) { return false; } // String comparison if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm) || !mMacAlgorithm.equals(other.mMacAlgorithm)) { return false; } // Object comparison if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey) || !isSecretKeyEqual(mMacKey, other.mMacKey)) { return false; } if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV()) || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) { return false; } return true; } private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) { final String keyFormat = key1.getFormat(); final String otherKeyFormat = key2.getFormat(); if (keyFormat == null) { if (keyFormat != otherKeyFormat) { return false; } if (key1.getEncoded() != key2.getEncoded()) { return false; } } else { if (!keyFormat.equals(key2.getFormat())) { return false; } if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) { return false; } } return true; } @Override public int hashCode() { int hash = 3; hash += 5 * mEncryptionAlgorithm.hashCode(); hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV()); hash += 11 * mEncryptionKey.hashCode(); hash += 13 * mMacAlgorithm.hashCode(); hash += 17 * mMacKey.hashCode(); hash += 19 * Arrays.hashCode(mMacTag); hash += 23 * mAuthenticatedDataStart; hash += 29 * mEncryptedDataStart; hash += 31 * mDataEnd; return hash; } @Override public String toString() { final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX); sb.append("mEncryptionAlgorithm=\""); sb.append(mEncryptionAlgorithm); sb.append("\","); sb.append("mEncryptionSpec="); sb.append(mEncryptionSpec.toString()); sb.append("mEncryptionKey="); sb.append(mEncryptionKey.toString()); sb.append("mMacAlgorithm=\""); sb.append(mMacAlgorithm); sb.append("\","); sb.append("mMacSpec="); sb.append(mMacSpec.toString()); sb.append("mMacKey="); sb.append(mMacKey.toString()); sb.append(",mAuthenticatedDataStart="); sb.append(mAuthenticatedDataStart); sb.append(",mEncryptedDataStart="); sb.append(mEncryptedDataStart); sb.append(",mDataEnd="); sb.append(mDataEnd); sb.append('}'); return sb.toString(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mEncryptionAlgorithm); dest.writeInt(ENC_PARAMS_IV_PARAMETERS); dest.writeByteArray(mEncryptionSpec.getIV()); dest.writeSerializable(mEncryptionKey); dest.writeString(mMacAlgorithm); dest.writeInt(MAC_PARAMS_NONE); dest.writeByteArray(new byte[0]); dest.writeSerializable(mMacKey); dest.writeByteArray(mMacTag); dest.writeInt(mAuthenticatedDataStart); dest.writeInt(mEncryptedDataStart); dest.writeInt(mDataEnd); } private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException { mEncryptionAlgorithm = source.readString(); final int encParamType = source.readInt(); final byte[] encParamsEncoded = source.createByteArray(); mEncryptionKey = (SecretKey) source.readSerializable(); mMacAlgorithm = source.readString(); final int macParamType = source.readInt(); source.createByteArray(); // byte[] macParamsEncoded mMacKey = (SecretKey) source.readSerializable(); mMacTag = source.createByteArray(); mAuthenticatedDataStart = source.readInt(); mEncryptedDataStart = source.readInt(); mDataEnd = source.readInt(); switch (encParamType) { case ENC_PARAMS_IV_PARAMETERS: mEncryptionSpec = new IvParameterSpec(encParamsEncoded); break; default: throw new InvalidAlgorithmParameterException("Unknown parameter type " + encParamType); } switch (macParamType) { case MAC_PARAMS_NONE: mMacSpec = null; break; default: throw new InvalidAlgorithmParameterException("Unknown parameter type " + macParamType); } if (mEncryptionKey == null) { throw new NullPointerException("encryptionKey == null"); } } public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR = new Parcelable.Creator<ContainerEncryptionParams>() { public ContainerEncryptionParams createFromParcel(Parcel source) { try { return new ContainerEncryptionParams(source); } catch (InvalidAlgorithmParameterException e) { Slog.e(TAG, "Invalid algorithm parameters specified", e); return null; } } public ContainerEncryptionParams[] newArray(int size) { return new ContainerEncryptionParams[size]; } }; } No newline at end of file core/java/android/content/pm/IPackageManager.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageInstallObserver; import android.content.pm.IPackageDeleteObserver; Loading Loading @@ -362,7 +363,7 @@ interface IPackageManager { void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer, int flags, in String installerPackageName, in Uri verificationURI, in ManifestDigest manifestDigest); in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams); void verifyPendingInstall(int id, int verificationCode); Loading Loading
cmds/pm/src/com/android/commands/pm/Pm.java +131 −4 Original line number Diff line number Diff line Loading @@ -16,9 +16,12 @@ package com.android.commands.pm; import com.android.internal.content.PackageHelper; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; Loading @@ -40,17 +43,20 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import com.android.internal.content.PackageHelper; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.InvalidAlgorithmParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.WeakHashMap; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public final class Pm { IPackageManager mPm; Loading Loading @@ -763,6 +769,15 @@ public final class Pm { String installerPackageName = null; String opt; String algo = null; byte[] iv = null; byte[] key = null; String macAlgo = null; byte[] macKey = null; byte[] tag = null; while ((opt=nextOption()) != null) { if (opt.equals("-l")) { installFlags |= PackageManager.INSTALL_FORWARD_LOCK; Loading @@ -783,6 +798,48 @@ public final class Pm { } else if (opt.equals("-f")) { // Override if -s option is specified. installFlags |= PackageManager.INSTALL_INTERNAL; } else if (opt.equals("--algo")) { algo = nextOptionData(); if (algo == null) { System.err.println("Error: must supply argument for --algo"); showUsage(); return; } } else if (opt.equals("--iv")) { iv = hexToBytes(nextOptionData()); if (iv == null) { System.err.println("Error: must supply argument for --iv"); showUsage(); return; } } else if (opt.equals("--key")) { key = hexToBytes(nextOptionData()); if (key == null) { System.err.println("Error: must supply argument for --key"); showUsage(); return; } } else if (opt.equals("--macalgo")) { macAlgo = nextOptionData(); if (macAlgo == null) { System.err.println("Error: must supply argument for --macalgo"); showUsage(); return; } } else if (opt.equals("--mackey")) { macKey = hexToBytes(nextOptionData()); if (macKey == null) { System.err.println("Error: must supply argument for --mackey"); showUsage(); return; } } else if (opt.equals("--tag")) { tag = hexToBytes(nextOptionData()); if (tag == null) { System.err.println("Error: must supply argument for --tag"); showUsage(); return; } } else { System.err.println("Error: Unknown option: " + opt); showUsage(); Loading @@ -790,6 +847,44 @@ public final class Pm { } } final ContainerEncryptionParams encryptionParams; if (algo != null || iv != null || key != null || macAlgo != null || macKey != null || tag != null) { if (algo == null || iv == null || key == null) { System.err.println("Error: all of --algo, --iv, and --key must be specified"); showUsage(); return; } if (macAlgo != null || macKey != null || tag != null) { if (macAlgo == null || macKey == null || tag == null) { System.err.println("Error: all of --macalgo, --mackey, and --tag must " + "be specified"); showUsage(); return; } } try { final SecretKey encKey = new SecretKeySpec(key, "RAW"); final SecretKey macSecretKey; if (macKey == null || macKey.length == 0) { macSecretKey = null; } else { macSecretKey = new SecretKeySpec(macKey, "RAW"); } encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv), encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); return; } } else { encryptionParams = null; } final Uri apkURI; final Uri verificationURI; Loading @@ -816,7 +911,7 @@ public final class Pm { PackageInstallObserver obs = new PackageInstallObserver(); try { mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName, verificationURI, null); verificationURI, null, encryptionParams); synchronized (obs) { while (!obs.finished) { Loading @@ -839,6 +934,37 @@ public final class Pm { } } /** * Convert a string containing hex-encoded bytes to a byte array. * * @param input String containing hex-encoded bytes * @return input as an array of bytes */ private byte[] hexToBytes(String input) { if (input == null) { return null; } final int inputLength = input.length(); if ((inputLength % 2) != 0) { System.err.print("Invalid length; must be multiple of 2"); return null; } final int byteLength = inputLength / 2; final byte[] output = new byte[byteLength]; int inputIndex = 0; int byteIndex = 0; while (inputIndex < inputLength) { output[byteIndex++] = (byte) Integer.parseInt( input.substring(inputIndex, inputIndex + 2), 16); inputIndex += 2; } return output; } public void runCreateUser() { // Need to be run as root if (Process.myUid() != ROOT_UID) { Loading Loading @@ -1236,7 +1362,8 @@ public final class Pm { System.err.println(" pm list libraries"); System.err.println(" pm list users"); System.err.println(" pm path PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH"); System.err.println(" pm uninstall [-k] PACKAGE"); System.err.println(" pm clear PACKAGE"); System.err.println(" pm enable [--user USER_ID] PACKAGE_OR_COMPONENT"); Loading
core/java/android/app/ApplicationPackageManager.java +3 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.IntentSender; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageDeleteObserver; Loading Loading @@ -973,10 +974,10 @@ final class ApplicationPackageManager extends PackageManager { @Override public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer, int flags, String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) { ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) { try { mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName, verificationURI, manifestDigest); verificationURI, manifestDigest, encryptionParams); } catch (RemoteException e) { // Should never happen! } Loading
core/java/android/content/pm/ContainerEncryptionParams.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * Copyright 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; parcelable ContainerEncryptionParams;
core/java/android/content/pm/ContainerEncryptionParams.java 0 → 100644 +378 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content.pm; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.Slog; import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; /** * Represents encryption parameters used to read a container. * * @hide */ public class ContainerEncryptionParams implements Parcelable { protected static final String TAG = "ContainerEncryptionParams"; /** What we print out first when toString() is called. */ private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{"; /** * Parameter type for parceling that indicates the next parameters are * IvParameters. */ private static final int ENC_PARAMS_IV_PARAMETERS = 1; /** Parameter type for paceling that indicates there are no MAC parameters. */ private static final int MAC_PARAMS_NONE = 1; /** The encryption algorithm used. */ private final String mEncryptionAlgorithm; /** The parameter spec to be used for encryption. */ private final IvParameterSpec mEncryptionSpec; /** Secret key to be used for decryption. */ private final SecretKey mEncryptionKey; /** Algorithm name for the MAC to be used. */ private final String mMacAlgorithm; /** The parameter spec to be used for the MAC tag authentication. */ private final AlgorithmParameterSpec mMacSpec; /** Secret key to be used for MAC tag authentication. */ private final SecretKey mMacKey; /** MAC tag authenticating the data in the container. */ private final byte[] mMacTag; /** Offset into file where authenticated (e.g., MAC protected) data begins. */ private final int mAuthenticatedDataStart; /** Offset into file where encrypted data begins. */ private final int mEncryptedDataStart; /** * Offset into file for the end of encrypted data (and, by extension, * authenticated data) in file. */ private final int mDataEnd; public ContainerEncryptionParams(String encryptionAlgorithm, AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey) throws InvalidAlgorithmParameterException { this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1, -1); } /** * Creates container encryption specifications for installing from encrypted * containers. * * @param encryptionAlgorithm encryption algorithm to use; format matches * JCE * @param encryptionSpec algorithm parameter specification * @param encryptionKey key used for decryption * @param macAlgorithm MAC algorithm to use; format matches JCE * @param macSpec algorithm parameters specification, may be {@code null} * @param macKey key used for authentication (i.e., for the MAC tag) * @param authenticatedDataStart offset of start of authenticated data in * stream * @param encryptedDataStart offset of start of encrypted data in stream * @param dataEnd offset of the end of both the authenticated and encrypted * data * @throws InvalidAlgorithmParameterException */ public ContainerEncryptionParams(String encryptionAlgorithm, AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm, AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag, int authenticatedDataStart, int encryptedDataStart, int dataEnd) throws InvalidAlgorithmParameterException { if (TextUtils.isEmpty(encryptionAlgorithm)) { throw new NullPointerException("algorithm == null"); } else if (encryptionSpec == null) { throw new NullPointerException("encryptionSpec == null"); } else if (encryptionKey == null) { throw new NullPointerException("encryptionKey == null"); } if (!TextUtils.isEmpty(macAlgorithm)) { if (macKey == null) { throw new NullPointerException("macKey == null"); } } if (!(encryptionSpec instanceof IvParameterSpec)) { throw new InvalidAlgorithmParameterException( "Unknown parameter spec class; must be IvParameters"); } mEncryptionAlgorithm = encryptionAlgorithm; mEncryptionSpec = (IvParameterSpec) encryptionSpec; mEncryptionKey = encryptionKey; mMacAlgorithm = macAlgorithm; mMacSpec = macSpec; mMacKey = macKey; mMacTag = macTag; mAuthenticatedDataStart = authenticatedDataStart; mEncryptedDataStart = encryptedDataStart; mDataEnd = dataEnd; } public String getEncryptionAlgorithm() { return mEncryptionAlgorithm; } public AlgorithmParameterSpec getEncryptionSpec() { return mEncryptionSpec; } public SecretKey getEncryptionKey() { return mEncryptionKey; } public String getMacAlgorithm() { return mMacAlgorithm; } public AlgorithmParameterSpec getMacSpec() { return mMacSpec; } public SecretKey getMacKey() { return mMacKey; } public byte[] getMacTag() { return mMacTag; } public int getAuthenticatedDataStart() { return mAuthenticatedDataStart; } public int getEncryptedDataStart() { return mEncryptedDataStart; } public int getDataEnd() { return mDataEnd; } @Override public int describeContents() { return 0; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof ContainerEncryptionParams)) { return false; } final ContainerEncryptionParams other = (ContainerEncryptionParams) o; // Primitive comparison if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart) || (mEncryptedDataStart != other.mEncryptedDataStart) || (mDataEnd != other.mDataEnd)) { return false; } // String comparison if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm) || !mMacAlgorithm.equals(other.mMacAlgorithm)) { return false; } // Object comparison if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey) || !isSecretKeyEqual(mMacKey, other.mMacKey)) { return false; } if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV()) || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) { return false; } return true; } private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) { final String keyFormat = key1.getFormat(); final String otherKeyFormat = key2.getFormat(); if (keyFormat == null) { if (keyFormat != otherKeyFormat) { return false; } if (key1.getEncoded() != key2.getEncoded()) { return false; } } else { if (!keyFormat.equals(key2.getFormat())) { return false; } if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) { return false; } } return true; } @Override public int hashCode() { int hash = 3; hash += 5 * mEncryptionAlgorithm.hashCode(); hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV()); hash += 11 * mEncryptionKey.hashCode(); hash += 13 * mMacAlgorithm.hashCode(); hash += 17 * mMacKey.hashCode(); hash += 19 * Arrays.hashCode(mMacTag); hash += 23 * mAuthenticatedDataStart; hash += 29 * mEncryptedDataStart; hash += 31 * mDataEnd; return hash; } @Override public String toString() { final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX); sb.append("mEncryptionAlgorithm=\""); sb.append(mEncryptionAlgorithm); sb.append("\","); sb.append("mEncryptionSpec="); sb.append(mEncryptionSpec.toString()); sb.append("mEncryptionKey="); sb.append(mEncryptionKey.toString()); sb.append("mMacAlgorithm=\""); sb.append(mMacAlgorithm); sb.append("\","); sb.append("mMacSpec="); sb.append(mMacSpec.toString()); sb.append("mMacKey="); sb.append(mMacKey.toString()); sb.append(",mAuthenticatedDataStart="); sb.append(mAuthenticatedDataStart); sb.append(",mEncryptedDataStart="); sb.append(mEncryptedDataStart); sb.append(",mDataEnd="); sb.append(mDataEnd); sb.append('}'); return sb.toString(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mEncryptionAlgorithm); dest.writeInt(ENC_PARAMS_IV_PARAMETERS); dest.writeByteArray(mEncryptionSpec.getIV()); dest.writeSerializable(mEncryptionKey); dest.writeString(mMacAlgorithm); dest.writeInt(MAC_PARAMS_NONE); dest.writeByteArray(new byte[0]); dest.writeSerializable(mMacKey); dest.writeByteArray(mMacTag); dest.writeInt(mAuthenticatedDataStart); dest.writeInt(mEncryptedDataStart); dest.writeInt(mDataEnd); } private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException { mEncryptionAlgorithm = source.readString(); final int encParamType = source.readInt(); final byte[] encParamsEncoded = source.createByteArray(); mEncryptionKey = (SecretKey) source.readSerializable(); mMacAlgorithm = source.readString(); final int macParamType = source.readInt(); source.createByteArray(); // byte[] macParamsEncoded mMacKey = (SecretKey) source.readSerializable(); mMacTag = source.createByteArray(); mAuthenticatedDataStart = source.readInt(); mEncryptedDataStart = source.readInt(); mDataEnd = source.readInt(); switch (encParamType) { case ENC_PARAMS_IV_PARAMETERS: mEncryptionSpec = new IvParameterSpec(encParamsEncoded); break; default: throw new InvalidAlgorithmParameterException("Unknown parameter type " + encParamType); } switch (macParamType) { case MAC_PARAMS_NONE: mMacSpec = null; break; default: throw new InvalidAlgorithmParameterException("Unknown parameter type " + macParamType); } if (mEncryptionKey == null) { throw new NullPointerException("encryptionKey == null"); } } public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR = new Parcelable.Creator<ContainerEncryptionParams>() { public ContainerEncryptionParams createFromParcel(Parcel source) { try { return new ContainerEncryptionParams(source); } catch (InvalidAlgorithmParameterException e) { Slog.e(TAG, "Invalid algorithm parameters specified", e); return null; } } public ContainerEncryptionParams[] newArray(int size) { return new ContainerEncryptionParams[size]; } }; } No newline at end of file
core/java/android/content/pm/IPackageManager.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ContainerEncryptionParams; import android.content.pm.FeatureInfo; import android.content.pm.IPackageInstallObserver; import android.content.pm.IPackageDeleteObserver; Loading Loading @@ -362,7 +363,7 @@ interface IPackageManager { void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer, int flags, in String installerPackageName, in Uri verificationURI, in ManifestDigest manifestDigest); in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams); void verifyPendingInstall(int id, int verificationCode); Loading