1/* 2 * Copyright (C) 2017 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 */ 16package android.net; 17 18import android.annotation.StringDef; 19import android.os.Parcel; 20import android.os.Parcelable; 21import java.lang.annotation.Retention; 22import java.lang.annotation.RetentionPolicy; 23 24/** 25 * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to 26 * RFC 4301. 27 * 28 * @hide 29 */ 30public final class IpSecAlgorithm implements Parcelable { 31 32 /** 33 * AES-CBC Encryption/Ciphering Algorithm. 34 * 35 * <p>Valid lengths for this key are {128, 192, 256}. 36 */ 37 public static final String CRYPT_AES_CBC = "cbc(aes)"; 38 39 /** 40 * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new 41 * applications and is provided for legacy compatibility with 3gpp infrastructure. 42 * 43 * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 128. 44 */ 45 public static final String AUTH_HMAC_MD5 = "hmac(md5)"; 46 47 /** 48 * SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in 49 * new applications and is provided for legacy compatibility with 3gpp infrastructure. 50 * 51 * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 160. 52 */ 53 public static final String AUTH_HMAC_SHA1 = "hmac(sha1)"; 54 55 /** 56 * SHA256 HMAC Authentication/Integrity Algorithm. 57 * 58 * <p>Valid truncation lengths are multiples of 8 bits from 96 to (default) 256. 59 */ 60 public static final String AUTH_HMAC_SHA256 = "hmac(sha256)"; 61 62 /** 63 * SHA384 HMAC Authentication/Integrity Algorithm. 64 * 65 * <p>Valid truncation lengths are multiples of 8 bits from 192 to (default) 384. 66 */ 67 public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; 68 /** 69 * SHA512 HMAC Authentication/Integrity Algorithm 70 * 71 * <p>Valid truncation lengths are multiples of 8 bits from 256 to (default) 512. 72 */ 73 public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; 74 75 /** @hide */ 76 @StringDef({ 77 CRYPT_AES_CBC, 78 AUTH_HMAC_MD5, 79 AUTH_HMAC_SHA1, 80 AUTH_HMAC_SHA256, 81 AUTH_HMAC_SHA512 82 }) 83 @Retention(RetentionPolicy.SOURCE) 84 public @interface AlgorithmName {} 85 86 private final String mName; 87 private final byte[] mKey; 88 private final int mTruncLenBits; 89 90 /** 91 * Specify a IpSecAlgorithm of one of the supported types including the truncation length of the 92 * algorithm 93 * 94 * @param algorithm type for IpSec. 95 * @param key non-null Key padded to a multiple of 8 bits. 96 */ 97 public IpSecAlgorithm(String algorithm, byte[] key) { 98 this(algorithm, key, key.length * 8); 99 } 100 101 /** 102 * Specify a IpSecAlgorithm of one of the supported types including the truncation length of the 103 * algorithm 104 * 105 * @param algoName precise name of the algorithm to be used. 106 * @param key non-null Key padded to a multiple of 8 bits. 107 * @param truncLenBits the number of bits of output hash to use; only meaningful for 108 * Authentication. 109 */ 110 public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) { 111 if (!isTruncationLengthValid(algoName, truncLenBits)) { 112 throw new IllegalArgumentException("Unknown algorithm or invalid length"); 113 } 114 mName = algoName; 115 mKey = key.clone(); 116 mTruncLenBits = Math.min(truncLenBits, key.length * 8); 117 } 118 119 /** Retrieve the algorithm name */ 120 public String getName() { 121 return mName; 122 } 123 124 /** Retrieve the key for this algorithm */ 125 public byte[] getKey() { 126 return mKey.clone(); 127 } 128 129 /** 130 * Retrieve the truncation length, in bits, for the key in this algo. By default this will be 131 * the length in bits of the key. 132 */ 133 public int getTruncationLengthBits() { 134 return mTruncLenBits; 135 } 136 137 /* Parcelable Implementation */ 138 public int describeContents() { 139 return 0; 140 } 141 142 /** Write to parcel */ 143 public void writeToParcel(Parcel out, int flags) { 144 out.writeString(mName); 145 out.writeByteArray(mKey); 146 out.writeInt(mTruncLenBits); 147 } 148 149 /** Parcelable Creator */ 150 public static final Parcelable.Creator<IpSecAlgorithm> CREATOR = 151 new Parcelable.Creator<IpSecAlgorithm>() { 152 public IpSecAlgorithm createFromParcel(Parcel in) { 153 return new IpSecAlgorithm(in); 154 } 155 156 public IpSecAlgorithm[] newArray(int size) { 157 return new IpSecAlgorithm[size]; 158 } 159 }; 160 161 private IpSecAlgorithm(Parcel in) { 162 mName = in.readString(); 163 mKey = in.createByteArray(); 164 mTruncLenBits = in.readInt(); 165 } 166 167 private static boolean isTruncationLengthValid(String algo, int truncLenBits) { 168 switch (algo) { 169 case CRYPT_AES_CBC: 170 return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256); 171 case AUTH_HMAC_MD5: 172 return (truncLenBits >= 96 && truncLenBits <= 128); 173 case AUTH_HMAC_SHA1: 174 return (truncLenBits >= 96 && truncLenBits <= 160); 175 case AUTH_HMAC_SHA256: 176 return (truncLenBits >= 96 && truncLenBits <= 256); 177 case AUTH_HMAC_SHA384: 178 return (truncLenBits >= 192 && truncLenBits <= 384); 179 case AUTH_HMAC_SHA512: 180 return (truncLenBits >= 256 && truncLenBits <= 512); 181 default: 182 return false; 183 } 184 } 185}; 186