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]; 177fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } *pData = malloc(sizeof *pData); 178fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pData == NULL) { 179fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 180fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 181fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FwdLockGlue_DecryptKey(pSession->pEncryptedSessionKey, 182fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength, pData->key, KEY_SIZE); 183fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (result) { 184fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, &pData->sessionRoundKeys) != 0) { 185fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 186fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 187fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key. 188fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(pData->value, 0, KEY_SIZE); 189fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); 190fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, 191fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &pSession->encryptionRoundKeys) != 0) { 192fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 193fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 194fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key. 195fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pData->value[0]; 196fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); 197fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX_init(&pSession->signingContext); 198fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL); 199fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 200fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 201fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 202fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (!result) { 203fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = ENOSYS; 204fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 205fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(pData, 0, sizeof pData); // Zero out key data. 206fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pData); 207fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 208fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return result; 209fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 210fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 211fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 212fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Calculates the counter, treated as a 16-byte little-endian number, used to generate the keystream 213fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * for the given block. 214fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 215fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] pNonce A reference to the nonce. 216fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] blockIndex The index number of the block. 217fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[out] pCounter A reference to the counter. 218fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 219fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic void FwdLockFile_CalculateCounter(const unsigned char *pNonce, 220fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockIndex, 221fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char *pCounter) { 222fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char carry = 0; 223fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t i = 0; 224fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (; i < sizeof blockIndex; ++i) { 225fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char part = pNonce[i] + (unsigned char)(blockIndex >> (i * CHAR_BIT)); 226fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pCounter[i] = part + carry; 227fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera carry = (part < pNonce[i] || pCounter[i] < part) ? 1 : 0; 228fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 229fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (; i < AES_BLOCK_SIZE; ++i) { 230fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pCounter[i] = pNonce[i] + carry; 231fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera carry = (pCounter[i] < pNonce[i]) ? 1 : 0; 232fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 233fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 234fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 235fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 236fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Decrypts the byte at the current file position using AES-128-CTR. In CTR (or "counter") mode, 237fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * encryption and decryption are performed using the same algorithm. 238fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 239fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a file session. 240fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] pByte The byte to decrypt. 241fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 242fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheravoid FwdLockFile_DecryptByte(FwdLockFile_Session_t * pSession, unsigned char *pByte) { 243fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockIndex = pSession->filePos / AES_BLOCK_SIZE; 244fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera uint64_t blockOffset = pSession->filePos % AES_BLOCK_SIZE; 245fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (blockIndex != pSession->blockIndex) { 246fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The first 16 bytes of the encrypted session key is used as the nonce. 247fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char counter[AES_BLOCK_SIZE]; 248fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_CalculateCounter(pSession->pEncryptedSessionKey, blockIndex, counter); 249fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(counter, pSession->keyStream, &pSession->encryptionRoundKeys); 250fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->blockIndex = blockIndex; 251fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 252fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pByte ^= pSession->keyStream[blockOffset]; 253fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 254fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 255fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_attach(int fileDesc) { 256fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_AcquireSession(fileDesc); 257fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId >= 0) { 258fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 259fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int isSuccess = FALSE; 260fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (read(fileDesc, pSession->topHeader, TOP_HEADER_SIZE) == TOP_HEADER_SIZE && 261fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcmp(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate) == 0) { 262fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTypeLength = pSession->topHeader[CONTENT_TYPE_LENGTH_POS]; 263fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(pSession->contentTypeLength <= UCHAR_MAX); // Untaint scalar for code checkers. 264fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pContentType = malloc(pSession->contentTypeLength + 1); 265fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->pContentType != NULL && 266fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->pContentType, pSession->contentTypeLength) == 267fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (ssize_t)pSession->contentTypeLength) { 268fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pContentType[pSession->contentTypeLength] = '\0'; 269fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE); 270fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength); 271fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->pEncryptedSessionKey != NULL && 272fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->pEncryptedSessionKey, 273fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength) == 274fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (ssize_t)pSession->encryptedSessionKeyLength && 275fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->dataSignature, SHA1_HASH_SIZE) == 276fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SHA1_HASH_SIZE && 277fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(fileDesc, pSession->headerSignature, SHA1_HASH_SIZE) == 278fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SHA1_HASH_SIZE) { 279fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera isSuccess = FwdLockFile_DeriveKeys(pSession); 280fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 281fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 282fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 283fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (isSuccess) { 284fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->dataOffset = pSession->contentTypeLength + 285fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength + TOP_HEADER_SIZE + 2 * SHA1_HASH_SIZE; 286fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->filePos = 0; 287fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->blockIndex = INVALID_BLOCK_INDEX; 288fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 289fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_ReleaseSession(sessionId); 290fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionId = -1; 291fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 292fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 293fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return (sessionId >= 0) ? 0 : -1; 294fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 295fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 296fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherassize_t FwdLockFile_read(int fileDesc, void *pBuffer, size_t numBytes) { 297fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t numBytesRead; 298fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 299fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 300fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera numBytesRead = -1; 301fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 302fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 303fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t i; 304fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera numBytesRead = read(pSession->fileDesc, pBuffer, numBytes); 305fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < numBytesRead; ++i) { 306fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_DecryptByte(pSession, &((unsigned char *)pBuffer)[i]); 307fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pSession->filePos; 308fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 309fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 310fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return numBytesRead; 311fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 312fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 313fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraoff64_t FwdLockFile_lseek(int fileDesc, off64_t offset, int whence) { 314fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera off64_t newFilePos; 315fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 316fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 317fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = INVALID_OFFSET; 318fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 319fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 320fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (whence) { 321fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case SEEK_SET: 322fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = lseek64(pSession->fileDesc, pSession->dataOffset + offset, whence); 323fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 324fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case SEEK_CUR: 325fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case SEEK_END: 326fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = lseek64(pSession->fileDesc, offset, whence); 327fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 328fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 329fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EINVAL; 330fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = INVALID_OFFSET; 331fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 332fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 333fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (newFilePos != INVALID_OFFSET) { 334fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (newFilePos < pSession->dataOffset) { 335fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The new file position is illegal for an internal Forward Lock file. Restore the 336fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // original file position. 337fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos, 338fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SEEK_SET); 339fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera errno = EINVAL; 340fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = INVALID_OFFSET; 341fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 342fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The return value should be the file position that lseek64() would have returned 343fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // for the embedded content file. 344fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->filePos = newFilePos - pSession->dataOffset; 345fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera newFilePos = pSession->filePos; 346fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 347fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 348fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 349fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return newFilePos; 350fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 351fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 352fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_detach(int fileDesc) { 353fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 354fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 355fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return -1; 356fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 357fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX_cleanup(&sessionPtrs[sessionId]->signingContext); 358fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_ReleaseSession(sessionId); 359fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return 0; 360fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 361fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 362fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_close(int fileDesc) { 363fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return (FwdLockFile_detach(fileDesc) == 0) ? close(fileDesc) : -1; 364fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 365fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 366fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_CheckDataIntegrity(int fileDesc) { 367fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int result; 368fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 369fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 370fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 371fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 372fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera struct FwdLockFile_CheckDataIntegrity_Data { 373fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char signature[SHA1_HASH_SIZE]; 374fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char buffer[SIG_CALC_BUFFER_SIZE]; 375fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } *pData = malloc(sizeof *pData); 376fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pData == NULL) { 377fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 378fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 379fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 380fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (lseek64(pSession->fileDesc, pSession->dataOffset, SEEK_SET) != 381fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->dataOffset) { 382fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 383fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 384fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t numBytesRead; 38590855078eb989944bca1824058d7231cd68e5021Henrik B Andersson unsigned int signatureSize = SHA1_HASH_SIZE; 386fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera while ((numBytesRead = 387fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera read(pSession->fileDesc, pData->buffer, SIG_CALC_BUFFER_SIZE)) > 0) { 388fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pData->buffer, (size_t)numBytesRead); 389fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 390fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (numBytesRead < 0) { 391fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 392fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 393fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Final(&pSession->signingContext, pData->signature, &signatureSize); 394fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(signatureSize == SHA1_HASH_SIZE); 39590855078eb989944bca1824058d7231cd68e5021Henrik B Andersson result = memcmp(pData->signature, pSession->dataSignature, SHA1_HASH_SIZE) == 0; 396fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 397fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); 398fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (void)lseek64(pSession->fileDesc, pSession->dataOffset + pSession->filePos, 399fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SEEK_SET); 400fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 401fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pData); 402fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 403fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 404fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return result; 405fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 406fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 407fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_CheckHeaderIntegrity(int fileDesc) { 408fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int result; 409fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 410fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 411fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera result = FALSE; 412fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 413fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockFile_Session_t *pSession = sessionPtrs[sessionId]; 414fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char signature[SHA1_HASH_SIZE]; 41590855078eb989944bca1824058d7231cd68e5021Henrik B Andersson unsigned int signatureSize = SHA1_HASH_SIZE; 416fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE); 417fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->pContentType, 418fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTypeLength); 419fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey, 420fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength); 42190855078eb989944bca1824058d7231cd68e5021Henrik B Andersson HMAC_Update(&pSession->signingContext, pSession->dataSignature, SHA1_HASH_SIZE); 422fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Final(&pSession->signingContext, signature, &signatureSize); 423fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(signatureSize == SHA1_HASH_SIZE); 42490855078eb989944bca1824058d7231cd68e5021Henrik B Andersson result = memcmp(signature, pSession->headerSignature, SHA1_HASH_SIZE) == 0; 425fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); 426fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 427fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return result; 428fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 429fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 430fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockFile_CheckIntegrity(int fileDesc) { 431fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockFile_CheckHeaderIntegrity(fileDesc) && FwdLockFile_CheckDataIntegrity(fileDesc); 432fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 433fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 434fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraconst char *FwdLockFile_GetContentType(int fileDesc) { 435fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = FwdLockFile_FindSession(fileDesc); 436fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionId < 0) { 437fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return NULL; 438fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 439fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return sessionPtrs[sessionId]->pContentType; 440fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 441