1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.devicepolicy; 18 19 import android.os.Parcel; 20 import android.os.Parcelable; 21 import android.util.Log; 22 23 import java.security.KeyFactory; 24 import java.security.NoSuchAlgorithmException; 25 import java.security.PrivateKey; 26 import java.security.spec.InvalidKeySpecException; 27 import java.security.spec.PKCS8EncodedKeySpec; 28 29 import javax.security.auth.DestroyFailedException; 30 31 /** 32 * A {@link PrivateKey} that can be transmitted as a {@link Parcelable}. 33 * 34 * <p>TODO(b/191150645): it's needed because the {@code PrivateKey} returned by {@code KeyFactory} 35 * does not properly implements {@code Serializable}. 36 */ 37 public final class ParcelablePrivateKey implements PrivateKey, Parcelable { 38 39 private static final long serialVersionUID = 1L; 40 41 private static final String TAG = ParcelablePrivateKey.class.getSimpleName(); 42 43 private final String mAlgorithm; 44 private final byte[] mEncodedKey; 45 private final PrivateKey mPrivateKey; 46 47 /** 48 * Default constructor. 49 */ ParcelablePrivateKey(String algorithm, byte[] encodedKey)50 public ParcelablePrivateKey(String algorithm, byte[] encodedKey) 51 throws NoSuchAlgorithmException, InvalidKeySpecException { 52 mAlgorithm = algorithm; 53 mEncodedKey = encodedKey; 54 mPrivateKey = KeyFactory.getInstance(algorithm).generatePrivate( 55 new PKCS8EncodedKeySpec(encodedKey)); 56 Log.d(TAG, "ParcelablePrivateKey(): algorithm=" + algorithm 57 + ", encodedKey.length=" + encodedKey.length 58 + " pk.format=" + mPrivateKey.getFormat() 59 + " pk.length=" + mPrivateKey.getEncoded().length); 60 } 61 62 @Override getAlgorithm()63 public String getAlgorithm() { 64 return mPrivateKey.getAlgorithm(); 65 } 66 67 @Override getFormat()68 public String getFormat() { 69 return mPrivateKey.getFormat(); 70 } 71 72 @Override getEncoded()73 public byte[] getEncoded() { 74 return mPrivateKey.getEncoded(); 75 } 76 77 @Override destroy()78 public void destroy() throws DestroyFailedException { 79 mPrivateKey.destroy(); 80 } 81 82 @Override isDestroyed()83 public boolean isDestroyed() { 84 return mPrivateKey.isDestroyed(); 85 } 86 87 @Override describeContents()88 public int describeContents() { 89 return 0; 90 } 91 92 @Override writeToParcel(Parcel dest, int flags)93 public void writeToParcel(Parcel dest, int flags) { 94 dest.writeString(mAlgorithm); 95 dest.writeInt(mEncodedKey.length); 96 dest.writeByteArray(mEncodedKey); 97 } 98 99 @Override toString()100 public String toString() { 101 return "ParcelablePrivateKey[algorithm=" + mAlgorithm 102 + ", length=" + mEncodedKey.length + ']'; 103 } 104 105 public static final Parcelable.Creator<ParcelablePrivateKey> CREATOR = 106 new Parcelable.Creator<ParcelablePrivateKey>() { 107 108 public ParcelablePrivateKey createFromParcel(Parcel in) { 109 String algorithm = in.readString(); 110 int arrayLength = in.readInt(); 111 byte[] key = new byte[arrayLength]; 112 in.readByteArray(key); 113 try { 114 return new ParcelablePrivateKey(algorithm, key); 115 } catch (Exception e) { 116 throw new IllegalArgumentException("could not parse key: algorithm=" + algorithm 117 + ", key_size=" + arrayLength, e); 118 } 119 } 120 121 public ParcelablePrivateKey[] newArray(int size) { 122 return new ParcelablePrivateKey[size]; 123 } 124 }; 125 126 } 127