1fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/* 2fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Copyright (C) 2010 The Android Open Source Project 3fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 4fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Licensed under the Apache License, Version 2.0 (the "License"); 5fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * you may not use this file except in compliance with the License. 6fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * You may obtain a copy of the License at 7fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 8fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * http://www.apache.org/licenses/LICENSE-2.0 9fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 10fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Unless required by applicable law or agreed to in writing, software 11fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * distributed under the License is distributed on an "AS IS" BASIS, 12fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * See the License for the specific language governing permissions and 14fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * limitations under the License. 15fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 16fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 179c78e8681dafcdf265bc733875bad436ef9ec220James Dong#include <utils/Log.h> 18fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <assert.h> 19fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <errno.h> 20fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <fcntl.h> 21fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <limits.h> 22fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <pthread.h> 23fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <stdlib.h> 24fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <string.h> 25fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <unistd.h> 26fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <openssl/aes.h> 27fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <openssl/hmac.h> 28fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 29fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include "FwdLockFile.h" 30fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include "FwdLockGlue.h" 31fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 32fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define TRUE 1 33fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FALSE 0 34fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 35fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define INVALID_OFFSET ((off64_t)-1) 36fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 37fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define INVALID_BLOCK_INDEX ((uint64_t)-1) 38fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 39fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define MAX_NUM_SESSIONS 128 40fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 41fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define KEY_SIZE AES_BLOCK_SIZE 42fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define KEY_SIZE_IN_BITS (KEY_SIZE * 8) 43fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 44fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define SHA1_HASH_SIZE 20 45fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define SHA1_BLOCK_SIZE 64 46fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 47fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FWD_LOCK_VERSION 0 48fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FWD_LOCK_SUBFORMAT 0 49fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define USAGE_RESTRICTION_FLAGS 0 50fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define CONTENT_TYPE_LENGTH_POS 7 51fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define TOP_HEADER_SIZE 8 52fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 53fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define SIG_CALC_BUFFER_SIZE (16 * SHA1_BLOCK_SIZE) 54fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 55fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 56fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Data type for the per-file state information needed by the decoder. 57fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 58fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheratypedef struct FwdLockFile_Session { 59fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int fileDesc; 60fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char topHeader[TOP_HEADER_SIZE]; 61fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera char *pContentType; 62fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t contentTypeLength; 63fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera void *pEncryptedSessionKey; 64fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t encryptedSessionKeyLength; 65fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char dataSignature[SHA1_HASH_SIZE]; 66fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char headerSignature[SHA1_HASH_SIZE]; 67fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera off64_t dataOffset; 68fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera off64_t filePos; 69fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_KEY encryptionRoundKeys; 70fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX signingContext; 71fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char keyStream[AES_BLOCK_SIZE]; 72fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockIndex; 73fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} FwdLockFile_Session_t; 74fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 75fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockFile_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL }; 76fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 77fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER; 78fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 79fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const unsigned char topHeaderTemplate[] = 80fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS }; 81fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 82fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 83fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Acquires an unused file session for the given file descriptor. 84fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 85fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] fileDesc A file descriptor. 86fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 87fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A session ID. 88fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 89fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockFile_AcquireSession(int fileDesc) { 90fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = -1; 91fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (fileDesc < 0) { 92fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EBADF; 93fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 94fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int i; 95fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_lock(&sessionAcquisitionMutex); 96fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < MAX_NUM_SESSIONS; ++i) { 97fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS; 98fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionPtrs[candidateSessionId] == NULL) { 99fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[candidateSessionId] = malloc(sizeof **sessionPtrs); 100fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionPtrs[candidateSessionId] != NULL) { 101fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[candidateSessionId]->fileDesc = fileDesc; 102fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[candidateSessionId]->pContentType = NULL; 103fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[candidateSessionId]->pEncryptedSessionKey = NULL; 104fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionId = candidateSessionId; 105fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 106fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 107fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 108fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 109fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_unlock(&sessionAcquisitionMutex); 110fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (i == MAX_NUM_SESSIONS) { 1119c78e8681dafcdf265bc733875bad436ef9ec220James Dong ALOGE("Too many sessions opened at the same time"); 112fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = ENFILE; 113fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 114fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 115fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return sessionId; 116fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 117fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 118fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 11990855078eb989944bca1824058d7231cd68e5021Henrik B Andersson * Finds the file session associated with the given file descriptor. 120fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 121fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] fileDesc A file descriptor. 122fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 123fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A session ID. 124fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 125fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockFile_FindSession(int fileDesc) { 126fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = -1; 127fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (fileDesc < 0) { 128fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EBADF; 129fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 130fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int i; 131fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_lock(&sessionAcquisitionMutex); 132fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < MAX_NUM_SESSIONS; ++i) { 133fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int candidateSessionId = (fileDesc + i) % MAX_NUM_SESSIONS; 134fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionPtrs[candidateSessionId] != NULL && 135fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[candidateSessionId]->fileDesc == fileDesc) { 136fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionId = candidateSessionId; 137fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 138fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 139fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 140fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_unlock(&sessionAcquisitionMutex); 141fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (i == MAX_NUM_SESSIONS) { 142fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EBADF; 143fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 144fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 145fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return sessionId; 146fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 147fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 148fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 149fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Releases a file session. 150fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 151fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] sessionID A session ID. 152fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 153fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic void FwdLockFile_ReleaseSession(int sessionId) { 154fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_lock(&sessionAcquisitionMutex); 155fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL); 156fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(sessionPtrs[sessionId]->pContentType); 157fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(sessionPtrs[sessionId]->pEncryptedSessionKey); 158fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data. 159fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(sessionPtrs[sessionId]); 160fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[sessionId] = NULL; 161fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_unlock(&sessionAcquisitionMutex); 162fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 163fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 164fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 165fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Derives keys for encryption and signing from the encrypted session key. 166fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 167fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a file session. 168fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 169fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether key derivation was successful. 170fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 171fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockFile_DeriveKeys(FwdLockFile_Session_t * pSession) { 172fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int result; 173fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera struct FwdLockFile_DeriveKeys_Data { 174fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_KEY sessionRoundKeys; 175fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char value[KEY_SIZE]; 176fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char key[KEY_SIZE]; 1772d45dbd1910a7e51d383e8583017e6f26cd3498aHung Nguyen }; 1782d45dbd1910a7e51d383e8583017e6f26cd3498aHung Nguyen 1792d45dbd1910a7e51d383e8583017e6f26cd3498aHung Nguyen const size_t kSize = sizeof(struct FwdLockFile_DeriveKeys_Data); 1802d45dbd1910a7e51d383e8583017e6f26cd3498aHung Nguyen struct FwdLockFile_DeriveKeys_Data *pData = malloc(kSize); 181fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pData == NULL) { 182fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 183fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 184fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FwdLockGlue_DecryptKey(pSession->pEncryptedSessionKey, 185fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength, pData->key, KEY_SIZE); 186fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (result) { 187fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, &pData->sessionRoundKeys) != 0) { 188fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 189fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 190fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key. 191fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(pData->value, 0, KEY_SIZE); 192fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); 193fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, 194fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &pSession->encryptionRoundKeys) != 0) { 195fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 196fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 197fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key. 198fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pData->value[0]; 199fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); 200fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX_init(&pSession->signingContext); 201fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL); 202fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 203fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 204fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 205fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (!result) { 206fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = ENOSYS; 207fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 2082d45dbd1910a7e51d383e8583017e6f26cd3498aHung Nguyen memset(pData, 0, kSize); // Zero out key data. 209fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pData); 210fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 211fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return result; 212fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 213fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 214fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 215fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Calculates the counter, treated as a 16-byte little-endian number, used to generate the keystream 216fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * for the given block. 217fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 218fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] pNonce A reference to the nonce. 219fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] blockIndex The index number of the block. 220fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[out] pCounter A reference to the counter. 221fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 222fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic void FwdLockFile_CalculateCounter(const unsigned char *pNonce, 223fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockIndex, 224fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char *pCounter) { 225fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char carry = 0; 226fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t i = 0; 227fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (; i < sizeof blockIndex; ++i) { 228fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char part = pNonce[i] + (unsigned char)(blockIndex >> (i * CHAR_BIT)); 229fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pCounter[i] = part + carry; 230fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera carry = (part < pNonce[i] || pCounter[i] < part) ? 1 : 0; 231fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 232fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (; i < AES_BLOCK_SIZE; ++i) { 233fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pCounter[i] = pNonce[i] + carry; 234fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera carry = (pCounter[i] < pNonce[i]) ? 1 : 0; 235fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 236fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 237fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 238fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 239fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Decrypts the byte at the current file position using AES-128-CTR. In CTR (or "counter") mode, 240fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * encryption and decryption are performed using the same algorithm. 241fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 242fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a file session. 243fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] pByte The byte to decrypt. 244fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 245fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheravoid FwdLockFile_DecryptByte(FwdLockFile_Session_t * pSession, unsigned char *pByte) { 246fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockIndex = pSession->filePos / AES_BLOCK_SIZE; 247fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockOffset = pSession->filePos % AES_BLOCK_SIZE; 248fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (blockIndex != pSession->blockIndex) { 249fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The first 16 bytes of the encrypted session key is used as the nonce. 250fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char counter[AES_BLOCK_SIZE]; 251fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_CalculateCounter(pSession->pEncryptedSessionKey, blockIndex, counter); 252fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(counter, pSession->keyStream, &pSession->encryptionRoundKeys); 253fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->blockIndex = blockIndex; 254fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 255fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pByte ^= pSession->keyStream[blockOffset]; 256fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 257fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 258fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_attach(int fileDesc) { 259fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_AcquireSession(fileDesc); 260fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId >= 0) { 261fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 262fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int isSuccess = FALSE; 263fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (read(fileDesc, pSession->topHeader, TOP_HEADER_SIZE) == TOP_HEADER_SIZE && 264fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcmp(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate) == 0) { 265fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTypeLength = pSession->topHeader[CONTENT_TYPE_LENGTH_POS]; 266fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(pSession->contentTypeLength <= UCHAR_MAX); // Untaint scalar for code checkers. 267fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pContentType = malloc(pSession->contentTypeLength + 1); 268fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->pContentType != NULL && 269fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->pContentType, pSession->contentTypeLength) == 270fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (ssize_t)pSession->contentTypeLength) { 271fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pContentType[pSession->contentTypeLength] = '\0'; 272fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE); 273fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength); 274fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->pEncryptedSessionKey != NULL && 275fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->pEncryptedSessionKey, 276fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength) == 277fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (ssize_t)pSession->encryptedSessionKeyLength && 278fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->dataSignature, SHA1_HASH_SIZE) == 279fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SHA1_HASH_SIZE && 280fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->headerSignature, SHA1_HASH_SIZE) == 281fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SHA1_HASH_SIZE) { 282fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera isSuccess = FwdLockFile_DeriveKeys(pSession); 283fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 284fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 285fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 286fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (isSuccess) { 287fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->dataOffset = pSession->contentTypeLength + 288fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength + TOP_HEADER_SIZE + 2 * SHA1_HASH_SIZE; 289fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->filePos = 0; 290fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->blockIndex = INVALID_BLOCK_INDEX; 291fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 292fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_ReleaseSession(sessionId); 293fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionId = -1; 294fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 295fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 296fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return (sessionId >= 0) ? 0 : -1; 297fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 298fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 299fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherassize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes) { 300fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t numBytesRead; 301fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 302fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 303fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera numBytesRead = -1; 304fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 305fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 306fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t i; 307fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera numBytesRead = read(pSession->fileDesc, pBuffer, numBytes); 308fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < numBytesRead; ++i) { 309fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_DecryptByte(pSession, &((unsigned char *)pBuffer)[i]); 310fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pSession->filePos; 311fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 312fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 313fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return numBytesRead; 314fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 315fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 316fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraoff64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence) { 317fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera off64_t newFilePos; 318fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 319fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 320fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = INVALID_OFFSET; 321fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 322fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 323fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (whence) { 324fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case SEEK_SET: 325fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = lseek64(pSession->fileDesc, pSession->dataOffset + offset, whence); 326fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 327fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case SEEK_CUR: 328fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case SEEK_END: 329fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = lseek64(pSession->fileDesc, offset, whence); 330fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 331fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 332fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EINVAL; 333fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = INVALID_OFFSET; 334fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 335fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 336fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (newFilePos != INVALID_OFFSET) { 337fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (newFilePos < pSession->dataOffset) { 338fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The new file position is illegal for an internal Forward Lock file. Restore the 339fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // original file position. 340fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos, 341fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SEEK_SET); 342fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EINVAL; 343fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = INVALID_OFFSET; 344fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 345fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The return value should be the file position that lseek64() would have returned 346fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // for the embedded content file. 347fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->filePos = newFilePos - pSession->dataOffset; 348fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = pSession->filePos; 349fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 350fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 351fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 352fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return newFilePos; 353fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 354fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 355fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_detach(int fileDesc) { 356fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 357fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 358fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return -1; 359fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 360fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX_cleanup(&sessionPtrs[sessionId]->signingContext); 361fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_ReleaseSession(sessionId); 362fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return 0; 363fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 364fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 365fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_close(int fileDesc) { 366fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return (FwdLockFile_detach(fileDesc) == 0) ? close(fileDesc) : -1; 367fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 368fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 369fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_CheckDataIntegrity(int fileDesc) { 370fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int result; 371fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 372fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 373fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 374fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 375fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera struct FwdLockFile_CheckDataIntegrity_Data { 376fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char signature[SHA1_HASH_SIZE]; 377fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char buffer[SIG_CALC_BUFFER_SIZE]; 378fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } *pData = malloc(sizeof *pData); 379fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pData == NULL) { 380fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 381fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 382fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 383fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (lseek64(pSession->fileDesc, pSession->dataOffset, SEEK_SET) != 384fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->dataOffset) { 385fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 386fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 387fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t numBytesRead; 38890855078eb989944bca1824058d7231cd68e5021Henrik B Andersson unsigned int signatureSize = SHA1_HASH_SIZE; 389fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera while ((numBytesRead = 390fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(pSession->fileDesc, pData->buffer, SIG_CALC_BUFFER_SIZE)) > 0) { 391fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pData->buffer, (size_t)numBytesRead); 392fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 393fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (numBytesRead < 0) { 394fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 395fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 396fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize); 397fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(signatureSize == SHA1_HASH_SIZE); 39890855078eb989944bca1824058d7231cd68e5021Henrik B Andersson result = memcmp(pData->signature, pSession->dataSignature, SHA1_HASH_SIZE) == 0; 399fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 400fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); 401fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos, 402fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SEEK_SET); 403fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 404fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pData); 405fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 406fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 407fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return result; 408fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 409fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 410fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_CheckHeaderIntegrity(int fileDesc) { 411fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int result; 412fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 413fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 414fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 415fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 416fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 417fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char signature[SHA1_HASH_SIZE]; 41890855078eb989944bca1824058d7231cd68e5021Henrik B Andersson unsigned int signatureSize = SHA1_HASH_SIZE; 419fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE); 420fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType, 421fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTypeLength); 422fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey, 423fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength); 42490855078eb989944bca1824058d7231cd68e5021Henrik B Andersson HMAC_Update(&pSession->signingContext, pSession->dataSignature, SHA1_HASH_SIZE); 425fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Final(&pSession->signingContext, signature, &signatureSize); 426fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(signatureSize == SHA1_HASH_SIZE); 42790855078eb989944bca1824058d7231cd68e5021Henrik B Andersson result = memcmp(signature, pSession->headerSignature, SHA1_HASH_SIZE) == 0; 428fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); 429fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 430fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return result; 431fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 432fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 433fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_CheckIntegrity(int fileDesc) { 434fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockFile_CheckHeaderIntegrity(fileDesc) && FwdLockFile_CheckDataIntegrity(fileDesc); 435fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 436fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 437fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraconst char *FwdLockFile_GetContentType(int fileDesc) { 438fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 439fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 440fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return NULL; 441fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 442fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return sessionPtrs[sessionId]->pContentType; 443fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 444