1ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward/* 2ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * Copyright (C) 2012 The Android Open Source Project 3ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * 4ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * Licensed under the Apache License, Version 2.0 (the "License"); 5ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * you may not use this file except in compliance with the License. 6ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * You may obtain a copy of the License at 7ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * 8ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * http://www.apache.org/licenses/LICENSE-2.0 9ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * 10ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * Unless required by applicable law or agreed to in writing, software 11ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * distributed under the License is distributed on an "AS IS" BASIS, 12ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * See the License for the specific language governing permissions and 14ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * limitations under the License. 15ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 16ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 17ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardpackage android.content.pm; 18ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 19ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport java.io.FilterInputStream; 20ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport java.io.IOException; 21ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport java.io.InputStream; 22ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 23ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardimport javax.crypto.Mac; 24ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 25ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward/** 26ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * An input stream filter that applies a MAC to the data passing through it. At 27ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * the end of the data that should be authenticated, the tag can be calculated. 28ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * After that, the stream should not be used. 29ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * 30ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * @hide 31ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 32ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Cowardpublic class MacAuthenticatedInputStream extends FilterInputStream { 33ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward private final Mac mMac; 34ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 35ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public MacAuthenticatedInputStream(InputStream in, Mac mac) { 36ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward super(in); 37ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 38ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mMac = mac; 39ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 40ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 41ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public boolean isTagEqual(byte[] tag) { 42ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward final byte[] actualTag = mMac.doFinal(); 43ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 44ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (tag == null || actualTag == null || tag.length != actualTag.length) { 45ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return false; 46ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 47ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 48ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward /* 49ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * Attempt to prevent timing attacks by doing the same amount of work 50ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * whether the first byte matches or not. Do not change this to a loop 51ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * that exits early when a byte does not match. 52ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward */ 53ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward int value = 0; 54ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward for (int i = 0; i < tag.length; i++) { 55ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward value |= tag[i] ^ actualTag[i]; 56ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 57ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 58ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return value == 0; 59ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 60ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 61ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward @Override 62ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public int read() throws IOException { 63ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward final int b = super.read(); 64ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (b >= 0) { 65ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mMac.update((byte) b); 66ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 67ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return b; 68ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 69ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 70ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward @Override 71ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward public int read(byte[] buffer, int offset, int count) throws IOException { 72ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward int numRead = super.read(buffer, offset, count); 73ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (numRead > 0) { 74ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward mMac.update(buffer, offset, numRead); 75ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 76ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward return numRead; 77ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward } 78ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward} 79