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 17fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <assert.h> 18fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <ctype.h> 19fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <fcntl.h> 20fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <limits.h> 21fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <pthread.h> 22fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <string.h> 23fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <sys/stat.h> 24fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <unistd.h> 25fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <openssl/aes.h> 26fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <openssl/hmac.h> 27fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 28fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include "FwdLockConv.h" 29fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include "FwdLockGlue.h" 30fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 31fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define TRUE 1 32fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FALSE 0 33fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 34fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define INVALID_OFFSET ((off64_t)-1) 35fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 36fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define MAX_NUM_SESSIONS 32 37fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 38fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define OUTPUT_BUFFER_SIZE_INCREMENT 1024 39fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define READ_BUFFER_SIZE 1024 40fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 41fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define MAX_BOUNDARY_LENGTH 70 42fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define MAX_DELIMITER_LENGTH (MAX_BOUNDARY_LENGTH + 4) 43fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 44fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define STRING_LENGTH_INCREMENT 25 45fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 46fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define KEY_SIZE AES_BLOCK_SIZE 47fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define KEY_SIZE_IN_BITS (KEY_SIZE * 8) 48fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 49fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define SHA1_HASH_SIZE 20 50fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 51fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FWD_LOCK_VERSION 0 52fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FWD_LOCK_SUBFORMAT 0 53fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define USAGE_RESTRICTION_FLAGS 0 54fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define CONTENT_TYPE_LENGTH_POS 7 55fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define TOP_HEADER_SIZE 8 56fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 57fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 58fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Data type for the parser states of the converter. 59fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 60fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheratypedef enum FwdLockConv_ParserState { 61fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ParserState_WantsOpenDelimiter, 62fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ParserState_WantsMimeHeaders, 63fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ParserState_WantsBinaryEncodedData, 64fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ParserState_WantsBase64EncodedData, 65fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ParserState_Done 66fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} FwdLockConv_ParserState_t; 67fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 68fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 69fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Data type for the scanner states of the converter. 70fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 71fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheratypedef enum FwdLockConv_ScannerState { 72fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsFirstDash, 73fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsSecondDash, 74fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsCR, 75fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsLF, 76fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsBoundary, 77fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsBoundaryEnd, 78fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsMimeHeaderNameStart, 79fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsMimeHeaderName, 80fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsMimeHeaderNameEnd, 81fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsContentTypeStart, 82fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsContentType, 83fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsContentTransferEncodingStart, 84fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_A_OR_I, 85fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_N, 86fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_A, 87fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_R, 88fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_Y, 89fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_S, 90fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_E, 91fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_6, 92fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_4, 93fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_B, 94fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_I, 95fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_Wants_T, 96fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsContentTransferEncodingEnd, 97fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsMimeHeaderValueEnd, 98fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsMimeHeadersEnd, 99fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsByte1, 100fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsByte1_AfterCRLF, 101fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsByte2, 102fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsByte3, 103fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsByte4, 104fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsPadding, 105fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsWhitespace, 106fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF, 107fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_WantsDelimiter 108fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} FwdLockConv_ScannerState_t; 109fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 110fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 111fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Data type for the content transfer encoding. 112fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 113fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheratypedef enum FwdLockConv_ContentTransferEncoding { 114fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_Undefined, 115fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_Binary, 116fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_Base64 117fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} FwdLockConv_ContentTransferEncoding_t; 118fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 119fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 120fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Data type for a dynamically growing string. 121fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 122fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheratypedef struct FwdLockConv_String { 123fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera char *ptr; 124fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t length; 125fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t maxLength; 126fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t lengthIncrement; 127fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} FwdLockConv_String_t; 128fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 129fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 130fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Data type for the per-file state information needed by the converter. 131fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 132fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheratypedef struct FwdLockConv_Session { 133fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ParserState_t parserState; 134fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_t scannerState; 135fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ScannerState_t savedScannerState; 136fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera off64_t numCharsConsumed; 137fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera char delimiter[MAX_DELIMITER_LENGTH]; 138fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t delimiterLength; 139fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t delimiterMatchPos; 140fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_String_t mimeHeaderName; 141fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_String_t contentType; 142fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_t contentTransferEncoding; 143fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char sessionKey[KEY_SIZE]; 144fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera void *pEncryptedSessionKey; 145fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t encryptedSessionKeyLength; 146fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_KEY encryptionRoundKeys; 147fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX signingContext; 148fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char topHeader[TOP_HEADER_SIZE]; 149fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char counter[AES_BLOCK_SIZE]; 150fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char keyStream[AES_BLOCK_SIZE]; 151fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int keyStreamIndex; 152fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char ch; 153fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t outputBufferSize; 154fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t dataOffset; 155fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t numDataBytes; 156fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} FwdLockConv_Session_t; 157fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 158fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Session_t *sessionPtrs[MAX_NUM_SESSIONS] = { NULL }; 159fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 160fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic pthread_mutex_t sessionAcquisitionMutex = PTHREAD_MUTEX_INITIALIZER; 161fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 162fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const FwdLockConv_String_t nullString = { NULL, 0, 0, STRING_LENGTH_INCREMENT }; 163fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 164fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const unsigned char topHeaderTemplate[] = 165fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera { 'F', 'W', 'L', 'K', FWD_LOCK_VERSION, FWD_LOCK_SUBFORMAT, USAGE_RESTRICTION_FLAGS }; 166fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 167fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strContent[] = "content-"; 168fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strType[] = "type"; 169fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strTransferEncoding[] = "transfer-encoding"; 170fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strTextPlain[] = "text/plain"; 171fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strApplicationVndOmaDrmRightsXml[] = "application/vnd.oma.drm.rights+xml"; 172fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strApplicationVndOmaDrmContent[] = "application/vnd.oma.drm.content"; 173fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 174fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const size_t strlenContent = sizeof strContent - 1; 175fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const size_t strlenTextPlain = sizeof strTextPlain - 1; 176fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 177fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const signed char base64Values[] = { 178fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 179fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 180fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 181fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, 182fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 183fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 184fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 185fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 186fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}; 187fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 188fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 189fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Acquires an unused converter session. 190fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 191fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A session ID. 192fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 193fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_AcquireSession() { 194fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId = -1; 195fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int i; 196fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_lock(&sessionAcquisitionMutex); 197fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < MAX_NUM_SESSIONS; ++i) { 198fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionPtrs[i] == NULL) { 199fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[i] = malloc(sizeof *sessionPtrs[i]); 200fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (sessionPtrs[i] != NULL) { 201fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionId = i; 202fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 203fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 204fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 205fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 206fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_unlock(&sessionAcquisitionMutex); 207fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return sessionId; 208fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 209fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 210fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 211fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Checks whether a session ID is in range and currently in use. 212fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 213fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] sessionID A session ID. 214fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 215fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the session ID is in range and currently in use. 216fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 217fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_IsValidSession(int sessionId) { 218fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return 0 <= sessionId && sessionId < MAX_NUM_SESSIONS && sessionPtrs[sessionId] != NULL; 219fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 220fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 221fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 222fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Releases a converter session. 223fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 224fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] sessionID A session ID. 225fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 226fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic void FwdLockConv_ReleaseSession(int sessionId) { 227fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_lock(&sessionAcquisitionMutex); 228fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera assert(FwdLockConv_IsValidSession(sessionId)); 229fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(sessionPtrs[sessionId], 0, sizeof *sessionPtrs[sessionId]); // Zero out key data. 230fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(sessionPtrs[sessionId]); 231fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera sessionPtrs[sessionId] = NULL; 232fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pthread_mutex_unlock(&sessionAcquisitionMutex); 233fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 234fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 235fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 236fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Derives cryptographically independent keys for encryption and signing from the session key. 237fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 238fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 239fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 240fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 241fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 242fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_DeriveKeys(FwdLockConv_Session_t *pSession) { 243fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 244fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera struct FwdLockConv_DeriveKeys_Data { 245fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_KEY sessionRoundKeys; 246fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char value[KEY_SIZE]; 247fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char key[KEY_SIZE]; 248fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } *pData = malloc(sizeof *pData); 249fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pData == NULL) { 250fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OutOfMemory; 251fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 252fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (AES_set_encrypt_key(pSession->sessionKey, KEY_SIZE_IN_BITS, 253fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &pData->sessionRoundKeys) != 0) { 254fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 255fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 256fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Encrypt the 16-byte value {0, 0, ..., 0} to produce the encryption key. 257fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(pData->value, 0, KEY_SIZE); 258fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); 259fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (AES_set_encrypt_key(pData->key, KEY_SIZE_IN_BITS, 260fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &pSession->encryptionRoundKeys) != 0) { 261fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 262fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 263fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Encrypt the 16-byte value {1, 0, ..., 0} to produce the signing key. 264fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pData->value[0]; 265fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pData->value, pData->key, &pData->sessionRoundKeys); 266fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX_init(&pSession->signingContext); 267fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, pData->key, KEY_SIZE, EVP_sha1(), NULL); 268fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OK; 269fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 270fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 271fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(pData, 0, sizeof pData); // Zero out key data. 272fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pData); 273fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 274fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 275fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 276fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 277fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 27890855078eb989944bca1824058d7231cd68e5021Henrik B Andersson * Checks whether a given character is valid in a boundary. Allows some non-standard characters that 27990855078eb989944bca1824058d7231cd68e5021Henrik B Andersson * are invalid according to RFC 2046 but nevertheless used by one vendor's DRM packager. Note that 28090855078eb989944bca1824058d7231cd68e5021Henrik B Andersson * the boundary may contain leading and internal spaces. 281fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 282fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to check. 283fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 284fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the given character is valid in a boundary. 285fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 286fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_IsBoundaryChar(int ch) { 28790855078eb989944bca1824058d7231cd68e5021Henrik B Andersson return isalnum(ch) || ch == '\'' || ch == '(' || ch == ')' || ch == '+' || ch == '_' || 28890855078eb989944bca1824058d7231cd68e5021Henrik B Andersson ch == ',' || ch == '-' || ch == '.' || ch == '/' || ch == ':' || ch == '=' || 28990855078eb989944bca1824058d7231cd68e5021Henrik B Andersson ch == '?' || ch == ' ' || ch == '%' || ch == '[' || ch == '&' || ch == '*' || ch == '^'; 290fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 291fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 292fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 293fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Checks whether a given character should be considered whitespace, using a narrower definition 294fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * than the standard-library isspace() function. 295fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 296fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to check. 297fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 298fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the given character should be considered whitespace. 299fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 300fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_IsWhitespace(int ch) { 301fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return ch == ' ' || ch == '\t'; 302fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 303fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 304fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 305fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Removes trailing spaces from the delimiter. 306fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 307fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 308fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 309fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 310fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 311fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_RightTrimDelimiter(FwdLockConv_Session_t *pSession) { 312fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera while (pSession->delimiterLength > 4 && 313fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiter[pSession->delimiterLength - 1] == ' ') { 314fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera --pSession->delimiterLength; 315fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 316fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->delimiterLength > 4) { 317fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OK; 318fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 319fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_SyntaxError; 320fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 321fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 322fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 323fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Matches the open delimiter. 324fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 325fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 326fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch A character. 327fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 328fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 329fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 330fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_MatchOpenDelimiter(FwdLockConv_Session_t *pSession, 331fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int ch) { 332fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status = FwdLockConv_Status_OK; 333fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (pSession->scannerState) { 334fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsFirstDash: 335fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '-') { 336fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash; 337fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 338fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 339fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 340fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 341fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 342fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 343fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsSecondDash: 344fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '-') { 345fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The delimiter starts with "\r\n--" (the open delimiter may omit the initial "\r\n"). 346fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The rest is the user-defined boundary that should come next. 347fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiter[0] = '\r'; 348fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiter[1] = '\n'; 349fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiter[2] = '-'; 350fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiter[3] = '-'; 351fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiterLength = 4; 352fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsBoundary; 353fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 354fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 355fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 356fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 357fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 358fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 359fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsCR: 360fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\r') { 361fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 362fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 363fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 364fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsLF: 365fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\n') { 366fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; 367fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch != '\r') { 368fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 369fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 370fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 371fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsBoundary: 372fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsBoundaryChar(ch)) { 373fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The boundary may contain leading and internal spaces, so trailing spaces will also be 374fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // matched here. These will be removed later. 375fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->delimiterLength < MAX_DELIMITER_LENGTH) { 376fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiter[pSession->delimiterLength++] = ch; 377fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch != ' ') { 378fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 379fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 380fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 381fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_RightTrimDelimiter(pSession); 382fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 383fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd; 384fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 385fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\t') { 386fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_RightTrimDelimiter(pSession); 387fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 388fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; 389fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 390fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 391fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 392fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 393fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 394fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsWhitespace: 395fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\r') { 396fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsBoundaryEnd; 397fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 398fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 399fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 400fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 401fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsBoundaryEnd: 402fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\n') { 403fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->parserState = FwdLockConv_ParserState_WantsMimeHeaders; 404fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart; 405fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 406fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 407fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 408fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 409fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 410fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 411fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 412fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 413fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 414fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 415fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 416fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 417fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Checks whether a given character is valid in a MIME header name. 418fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 419fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to check. 420fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 421fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the given character is valid in a MIME header name. 422fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 423fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_IsMimeHeaderNameChar(int ch) { 424fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return isgraph(ch) && ch != ':'; 425fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 426fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 427fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 428fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Checks whether a given character is valid in a MIME header value. 429fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 430fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to check. 431fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 432fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the given character is valid in a MIME header value. 433fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 434fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_IsMimeHeaderValueChar(int ch) { 435fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return isgraph(ch) && ch != ';'; 436fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 437fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 438fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 439fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Appends a character to the specified dynamically growing string. 440fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 441fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pString A reference to a dynamically growing string. 442fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to append. 443fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 444fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 445fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 446fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_StringAppend(FwdLockConv_String_t *pString, int ch) { 447fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pString->length == pString->maxLength) { 448fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t newMaxLength = pString->maxLength + pString->lengthIncrement; 449fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera char *newPtr = realloc(pString->ptr, newMaxLength + 1); 450fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (newPtr == NULL) { 451fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OutOfMemory; 452fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 453fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pString->ptr = newPtr; 454fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pString->maxLength = newMaxLength; 455fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 456fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pString->ptr[pString->length++] = ch; 457fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pString->ptr[pString->length] = '\0'; 458fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OK; 459fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 460fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 461fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 462fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Attempts to recognize the MIME header name and changes the scanner state accordingly. 463fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 464fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 465fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 466fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 467fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 468fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_RecognizeMimeHeaderName(FwdLockConv_Session_t *pSession) { 469fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status = FwdLockConv_Status_OK; 470fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (strncmp(pSession->mimeHeaderName.ptr, strContent, strlenContent) == 0) { 471fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strType) == 0) { 472fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentType.ptr == NULL) { 473fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsContentTypeStart; 474fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 475fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 476fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 477fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (strcmp(pSession->mimeHeaderName.ptr + strlenContent, strTransferEncoding) == 0) { 478fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentTransferEncoding == 479fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_Undefined) { 480fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingStart; 481fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 482fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 483fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 484fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 485fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 486fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 487fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 488fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 489fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 490fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 491fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 492fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 493fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 494fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Applies defaults to missing MIME header values. 495fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 496fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 497fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 498fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 499fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 500fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_ApplyDefaults(FwdLockConv_Session_t *pSession) { 501fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentType.ptr == NULL) { 502fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Content type is missing: default to "text/plain". 503fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType.ptr = malloc(sizeof strTextPlain); 504fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentType.ptr == NULL) { 505fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OutOfMemory; 506fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 507fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcpy(pSession->contentType.ptr, strTextPlain, sizeof strTextPlain); 508fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType.length = strlenTextPlain; 509fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType.maxLength = strlenTextPlain; 510fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 511fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentTransferEncoding == FwdLockConv_ContentTransferEncoding_Undefined) { 512fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Content transfer encoding is missing: default to binary. 513fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary; 514fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 515fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OK; 516fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 517fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 518fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 519fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Verifies that the content type is supported. 520fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 521fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 522fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 523fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 524fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 525fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_VerifyContentType(FwdLockConv_Session_t *pSession) { 526fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 527fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentType.ptr == NULL) { 528fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 529fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmRightsXml) == 0 || 530fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera strcmp(pSession->contentType.ptr, strApplicationVndOmaDrmContent) == 0) { 531fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedFileFormat; 532fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 533fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OK; 534fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 535fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 536fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 537fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 538fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 539fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Writes the header of the output file. 540fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 541fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 542fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[out] pOutput The output from the conversion process. 543fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 544fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 545fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 546fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_WriteHeader(FwdLockConv_Session_t *pSession, 547fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 548fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 549fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentType.length > UCHAR_MAX) { 550fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 551fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 552fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->outputBufferSize = OUTPUT_BUFFER_SIZE_INCREMENT; 553fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.pBuffer = malloc(pSession->outputBufferSize); 554fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pOutput->fromConvertData.pBuffer == NULL) { 555fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OutOfMemory; 556fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 557fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t encryptedSessionKeyPos = TOP_HEADER_SIZE + pSession->contentType.length; 558fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t dataSignaturePos = encryptedSessionKeyPos + pSession->encryptedSessionKeyLength; 559fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t headerSignaturePos = dataSignaturePos + SHA1_HASH_SIZE; 560fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->dataOffset = headerSignaturePos + SHA1_HASH_SIZE; 561fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcpy(pSession->topHeader, topHeaderTemplate, sizeof topHeaderTemplate); 562fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->topHeader[CONTENT_TYPE_LENGTH_POS] = 563fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera (unsigned char)pSession->contentType.length; 564fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcpy(pOutput->fromConvertData.pBuffer, pSession->topHeader, TOP_HEADER_SIZE); 565fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcpy((char *)pOutput->fromConvertData.pBuffer + TOP_HEADER_SIZE, 566fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType.ptr, pSession->contentType.length); 567fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcpy((char *)pOutput->fromConvertData.pBuffer + encryptedSessionKeyPos, 568fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pEncryptedSessionKey, pSession->encryptedSessionKeyLength); 569fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 570fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Set the signatures to all zeros for now; they will have to be updated later. 571fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset((char *)pOutput->fromConvertData.pBuffer + dataSignaturePos, 0, 572fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SHA1_HASH_SIZE); 573fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset((char *)pOutput->fromConvertData.pBuffer + headerSignaturePos, 0, 574fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SHA1_HASH_SIZE); 575fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 576fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.numBytes = pSession->dataOffset; 577fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OK; 578fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 579fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 580fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 581fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 582fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 583fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 584fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Matches the MIME headers. 585fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 586fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 587fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch A character. 588fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[out] pOutput The output from the conversion process. 589fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 590fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 591fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 592fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_MatchMimeHeaders(FwdLockConv_Session_t *pSession, 593fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int ch, 594fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 595fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status = FwdLockConv_Status_OK; 596fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (pSession->scannerState) { 597fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsMimeHeaderNameStart: 598fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsMimeHeaderNameChar(ch)) { 599fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->mimeHeaderName.length = 0; 600fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch)); 601fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 602fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderName; 603fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 604fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 605fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeadersEnd; 606fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 607fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 608fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 609fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 610fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsMimeHeaderName: 611fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsMimeHeaderNameChar(ch)) { 612fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_StringAppend(&pSession->mimeHeaderName, tolower(ch)); 613fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == ':') { 614fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_RecognizeMimeHeaderName(pSession); 615fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (FwdLockConv_IsWhitespace(ch)) { 616fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameEnd; 617fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 618fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 619fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 620fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 621fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsMimeHeaderNameEnd: 622fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == ':') { 623fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_RecognizeMimeHeaderName(pSession); 624fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 625fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 626fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 627fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 628fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsContentTypeStart: 629fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsMimeHeaderValueChar(ch)) { 630fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch)); 631fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 632fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsContentType; 633fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 634fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 635fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 636fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 637fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 638fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsContentType: 639fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsMimeHeaderValueChar(ch)) { 640fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_StringAppend(&pSession->contentType, tolower(ch)); 641fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == ';') { 642fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 643fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 644fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 645fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (FwdLockConv_IsWhitespace(ch)) { 646fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd; 647fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 648fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 649fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 650fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 651fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsContentTransferEncodingStart: 652fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'b' || ch == 'B') { 653fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_A_OR_I; 654fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '7' || ch == '8') { 655fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_B; 656fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 657fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 658fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 659fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 660fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_A_OR_I: 661fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'i' || ch == 'I') { 662fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_N; 663fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == 'a' || ch == 'A') { 664fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_S; 665fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 666fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 667fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 668fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 669fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_N: 670fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'n' || ch == 'N') { 671fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_A; 672fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 673fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 674fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 675fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 676fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_A: 677fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'a' || ch == 'A') { 678fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_R; 679fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 680fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 681fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 682fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 683fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_R: 684fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'r' || ch == 'R') { 685fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_Y; 686fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 687fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 688fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 689fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 690fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_Y: 691fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'y' || ch == 'Y') { 692fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary; 693fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd; 694fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 695fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 696fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 697fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 698fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_S: 699fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 's' || ch == 'S') { 700fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_E; 701fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 702fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 703fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 704fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 705fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_E: 706fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'e' || ch == 'E') { 707fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_6; 708fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 709fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 710fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 711fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 712fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_6: 713fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '6') { 714fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_4; 715fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 716fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 717fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 718fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 719fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_4: 720fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '4') { 721fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Base64; 722fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd; 723fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 724fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 725fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 726fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 727fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_B: 728fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'b' || ch == 'B') { 729fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_I; 730fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 731fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 732fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 733fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 734fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_I: 735fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 'i' || ch == 'I') { 736fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_Wants_T; 737fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 738fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 739fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 740fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 741fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_Wants_T: 742fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == 't' || ch == 'T') { 743fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTransferEncoding = FwdLockConv_ContentTransferEncoding_Binary; 744fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsContentTransferEncodingEnd; 745fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 746fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 747fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 748fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 749fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsContentTransferEncodingEnd: 750fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == ';') { 751fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 752fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 753fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 754fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (FwdLockConv_IsWhitespace(ch)) { 755fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderValueEnd; 756fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 757fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_UnsupportedContentTransferEncoding; 758fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 759fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 760fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsMimeHeaderValueEnd: 761fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == ';') { 762fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsCR; 763fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 764fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 765fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 766fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 767fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 768fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 769fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsCR: 770fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\r') { 771fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 772fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 773fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 774fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsLF: 775fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\n') { 776fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsMimeHeaderNameStart; 777fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 778fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 779fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 780fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 781fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsMimeHeadersEnd: 782fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\n') { 783fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_ApplyDefaults(pSession); 784fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 785fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_VerifyContentType(pSession); 786fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 787fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 788fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_WriteHeader(pSession, pOutput); 789fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 790fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 791fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->contentTransferEncoding == 792fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_Binary) { 793fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->parserState = FwdLockConv_ParserState_WantsBinaryEncodedData; 794fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 795fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->parserState = FwdLockConv_ParserState_WantsBase64EncodedData; 796fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 797fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsByte1; 798fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 799fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 800fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 801fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 802fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 803fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 804fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 805fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 806fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 807fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 808fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 809fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 810fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 811fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Increments the counter, treated as a 16-byte little-endian number, by one. 812fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 813fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 814fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 815fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic void FwdLockConv_IncrementCounter(FwdLockConv_Session_t *pSession) { 816fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t i = 0; 817fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera while ((++pSession->counter[i] == 0) && (++i < AES_BLOCK_SIZE)) 818fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ; 819fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 820fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 821fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 822fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Encrypts the given character and writes it to the output buffer. 823fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 824fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 825fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to encrypt and write. 826fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pOutput The output from the conversion process. 827fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 828fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 829fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 830fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_WriteEncryptedChar(FwdLockConv_Session_t *pSession, 831fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera unsigned char ch, 832fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 833fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pOutput->fromConvertData.numBytes == pSession->outputBufferSize) { 834fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera void *pBuffer; 835fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->outputBufferSize += OUTPUT_BUFFER_SIZE_INCREMENT; 836fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pBuffer = realloc(pOutput->fromConvertData.pBuffer, pSession->outputBufferSize); 837fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pBuffer == NULL) { 838fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OutOfMemory; 839fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 840fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.pBuffer = pBuffer; 841fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 842fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (++pSession->keyStreamIndex == AES_BLOCK_SIZE) { 843fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_IncrementCounter(pSession); 844fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->keyStreamIndex = 0; 845fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 846fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->keyStreamIndex == 0) { 847fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera AES_encrypt(pSession->counter, pSession->keyStream, &pSession->encryptionRoundKeys); 848fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 849fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ch ^= pSession->keyStream[pSession->keyStreamIndex]; 850fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ((unsigned char *)pOutput->fromConvertData.pBuffer)[pOutput->fromConvertData.numBytes++] = ch; 851fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pSession->numDataBytes; 852fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return FwdLockConv_Status_OK; 853fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 854fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 855fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 856fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Matches binary-encoded content data and encrypts it, while looking out for the close delimiter. 857fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 858fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 859fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch A character. 860fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pOutput The output from the conversion process. 861fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 862fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 863fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 864fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_MatchBinaryEncodedData(FwdLockConv_Session_t *pSession, 865fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int ch, 866fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 867fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status = FwdLockConv_Status_OK; 868fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (pSession->scannerState) { 869fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsByte1: 870fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch != pSession->delimiter[pSession->delimiterMatchPos]) { 871fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The partial match of the delimiter turned out to be spurious. Flush the matched bytes 872fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // to the output buffer and start over. 873fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t i; 874fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < pSession->delimiterMatchPos; ++i) { 875fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_WriteEncryptedChar(pSession, pSession->delimiter[i], pOutput); 876fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status != FwdLockConv_Status_OK) { 877fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 878fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 879fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 880fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiterMatchPos = 0; 881fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 882fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch != pSession->delimiter[pSession->delimiterMatchPos]) { 883fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The current character isn't part of the delimiter. Write it to the output buffer. 884fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_WriteEncryptedChar(pSession, ch, pOutput); 885fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) { 886fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The entire delimiter has been matched. The only valid characters now are the "--" 887fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // that complete the close delimiter (no more message parts are expected). 888fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; 889fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 890fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 891fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsFirstDash: 892fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '-') { 893fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash; 894fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 895fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 896fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 897fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 898fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsSecondDash: 899fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '-') { 900fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->parserState = FwdLockConv_ParserState_Done; 901fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 902fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 903fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 904fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 905fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 906fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 907fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 908fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 909fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 910fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 911fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 912fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 913fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Checks whether a given character is valid in base64-encoded data. 914fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 915fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch The character to check. 916fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 917fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the given character is valid in base64-encoded data. 918fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 919fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockConv_IsBase64Char(int ch) { 920fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return 0 <= ch && ch <= 'z' && base64Values[ch] >= 0; 921fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 922fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 923fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 924fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Matches base64-encoded content data and encrypts it, while looking out for the close delimiter. 925fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 926fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 927fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch A character. 928fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pOutput The output from the conversion process. 929fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 930fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 931fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 932fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_MatchBase64EncodedData(FwdLockConv_Session_t *pSession, 933fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int ch, 934fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 935fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status = FwdLockConv_Status_OK; 936fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (pSession->scannerState) { 937fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsByte1: 938fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsByte1_AfterCRLF: 939fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsBase64Char(ch)) { 940fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->ch = base64Values[ch] << 2; 941fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsByte2; 942fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 943fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->savedScannerState = FwdLockConv_ScannerState_WantsByte1_AfterCRLF; 944fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 945fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '-') { 946fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->scannerState == FwdLockConv_ScannerState_WantsByte1_AfterCRLF) { 947fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiterMatchPos = 3; 948fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter; 949fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 950fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 951fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 952fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 953fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 954fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 955fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 956fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsByte2: 957fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsBase64Char(ch)) { 958fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->ch |= base64Values[ch] >> 4; 959fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput); 960fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 961fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->ch = base64Values[ch] << 4; 962fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsByte3; 963fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 964fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 965fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->savedScannerState = pSession->scannerState; 966fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 967fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 968fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 969fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 970fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 971fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsByte3: 972fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsBase64Char(ch)) { 973fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->ch |= base64Values[ch] >> 2; 974fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput); 975fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 976fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->ch = base64Values[ch] << 6; 977fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsByte4; 978fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 979fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 980fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->savedScannerState = pSession->scannerState; 981fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 982fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '=') { 983fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsPadding; 984fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 985fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 986fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 987fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 988fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsByte4: 989fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (FwdLockConv_IsBase64Char(ch)) { 990fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->ch |= base64Values[ch]; 991fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_WriteEncryptedChar(pSession, pSession->ch, pOutput); 992fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 993fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsByte1; 994fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 995fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '\r') { 996fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->savedScannerState = pSession->scannerState; 997fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 998fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '=') { 999fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; 1000fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockConv_IsWhitespace(ch)) { 1001fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1002fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1003fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1004fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsLF: 1005fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\n') { 1006fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = pSession->savedScannerState; 1007fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1008fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1009fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1010fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1011fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsPadding: 1012fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '=') { 1013fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; 1014fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1015fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1016fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1017fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1018fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsWhitespace: 1019fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF: 1020fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '\r') { 1021fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->savedScannerState = FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF; 1022fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsLF; 1023fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (ch == '-') { 1024fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->scannerState == FwdLockConv_ScannerState_WantsWhitespace_AfterCRLF) { 1025fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiterMatchPos = 3; 1026fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsDelimiter; 1027fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1028fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1029fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1030fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (FwdLockConv_IsWhitespace(ch)) { 1031fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsWhitespace; 1032fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1033fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1034fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1035fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1036fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsDelimiter: 1037fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch != pSession->delimiter[pSession->delimiterMatchPos]) { 1038fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1039fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (++pSession->delimiterMatchPos == pSession->delimiterLength) { 1040fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; 1041fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1042fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1043fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsFirstDash: 1044fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '-') { 1045fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsSecondDash; 1046fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1047fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1048fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1049fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1050fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ScannerState_WantsSecondDash: 1051fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (ch == '-') { 1052fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->parserState = FwdLockConv_ParserState_Done; 1053fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1054fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1055fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1056fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1057fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 1058fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 1059fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1060fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1061fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 1062fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 1063fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 1064fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/** 1065fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Pushes a single character into the converter's state machine. 1066fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 1067fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pSession A reference to a converter session. 1068fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] ch A character. 1069fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in,out] pOutput The output from the conversion process. 1070fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * 1071fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A status code. 1072fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */ 1073fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic FwdLockConv_Status_t FwdLockConv_PushChar(FwdLockConv_Session_t *pSession, 1074fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int ch, 1075fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 1076fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 1077fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ++pSession->numCharsConsumed; 1078fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera switch (pSession->parserState) { 1079fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ParserState_WantsOpenDelimiter: 1080fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_MatchOpenDelimiter(pSession, ch); 1081fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1082fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ParserState_WantsMimeHeaders: 1083fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_MatchMimeHeaders(pSession, ch, pOutput); 1084fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1085fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ParserState_WantsBinaryEncodedData: 1086fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_MatchBinaryEncodedData(pSession, ch, pOutput); 1087fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1088fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ParserState_WantsBase64EncodedData: 108990855078eb989944bca1824058d7231cd68e5021Henrik B Andersson if (ch == '\n' && pSession->scannerState != FwdLockConv_ScannerState_WantsLF) { 109090855078eb989944bca1824058d7231cd68e5021Henrik B Andersson // Repair base64-encoded data that doesn't have carriage returns in its line breaks. 109190855078eb989944bca1824058d7231cd68e5021Henrik B Andersson status = FwdLockConv_MatchBase64EncodedData(pSession, '\r', pOutput); 109290855078eb989944bca1824058d7231cd68e5021Henrik B Andersson if (status != FwdLockConv_Status_OK) { 109390855078eb989944bca1824058d7231cd68e5021Henrik B Andersson break; 109490855078eb989944bca1824058d7231cd68e5021Henrik B Andersson } 109590855078eb989944bca1824058d7231cd68e5021Henrik B Andersson } 1096fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_MatchBase64EncodedData(pSession, ch, pOutput); 1097fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1098fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera case FwdLockConv_ParserState_Done: 1099fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OK; 1100fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1101fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera default: 1102fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 1103fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1104fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1105fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 1106fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 1107fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 1108fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat DalbeheraFwdLockConv_Status_t FwdLockConv_OpenSession(int *pSessionId, FwdLockConv_Output_t *pOutput) { 1109fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 1110fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSessionId == NULL || pOutput == NULL) { 1111fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_InvalidArgument; 1112fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1113fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pSessionId = FwdLockConv_AcquireSession(); 1114fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (*pSessionId < 0) { 1115fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_TooManySessions; 1116fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1117fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Session_t *pSession = sessionPtrs[*pSessionId]; 1118fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength = FwdLockGlue_GetEncryptedKeyLength(KEY_SIZE); 1119fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->encryptedSessionKeyLength < AES_BLOCK_SIZE) { 1120fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // The encrypted session key is used as the CTR-mode nonce, so it must be at least 1121fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // the size of a single AES block. 1122fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 1123fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1124fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pEncryptedSessionKey = malloc(pSession->encryptedSessionKeyLength); 1125fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->pEncryptedSessionKey == NULL) { 1126fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OutOfMemory; 1127fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1128fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (!FwdLockGlue_GetRandomNumber(pSession->sessionKey, KEY_SIZE)) { 1129fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_RandomNumberGenerationFailed; 1130fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (!FwdLockGlue_EncryptKey(pSession->sessionKey, KEY_SIZE, 1131fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->pEncryptedSessionKey, 1132fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength)) { 1133fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_KeyEncryptionFailed; 1134fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1135fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_DeriveKeys(pSession); 1136fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1137fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 1138fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memset(pSession->sessionKey, 0, KEY_SIZE); // Zero out key data. 1139fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera memcpy(pSession->counter, pSession->pEncryptedSessionKey, AES_BLOCK_SIZE); 1140fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->parserState = FwdLockConv_ParserState_WantsOpenDelimiter; 1141fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->scannerState = FwdLockConv_ScannerState_WantsFirstDash; 1142fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->numCharsConsumed = 0; 1143fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->delimiterMatchPos = 0; 1144fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->mimeHeaderName = nullString; 1145fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType = nullString; 1146fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentTransferEncoding = 1147fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ContentTransferEncoding_Undefined; 1148fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->keyStreamIndex = -1; 1149fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.pBuffer = NULL; 1150fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.errorPos = INVALID_OFFSET; 1151fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1152fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pSession->pEncryptedSessionKey); 1153fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1154fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1155fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1156fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status != FwdLockConv_Status_OK) { 1157fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ReleaseSession(*pSessionId); 1158fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pSessionId = -1; 1159fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1160fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1161fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1162fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 1163fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 1164fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 1165fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat DalbeheraFwdLockConv_Status_t FwdLockConv_ConvertData(int sessionId, 1166fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera const void *pBuffer, 1167fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t numBytes, 1168fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t *pOutput) { 1169fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 1170fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (!FwdLockConv_IsValidSession(sessionId) || pBuffer == NULL || pOutput == NULL) { 1171fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_InvalidArgument; 1172fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1173fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera size_t i; 1174fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Session_t *pSession = sessionPtrs[sessionId]; 1175fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->dataOffset = 0; 1176fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->numDataBytes = 0; 1177fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.numBytes = 0; 1178fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OK; 1179fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 1180fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera for (i = 0; i < numBytes; ++i) { 1181fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_PushChar(pSession, ((char *)pBuffer)[i], pOutput); 1182fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status != FwdLockConv_Status_OK) { 1183fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1184fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1185fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1186fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 1187fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Update the data signature. 1188fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, 1189fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &((unsigned char *)pOutput->fromConvertData.pBuffer)[pSession->dataOffset], 1190fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->numDataBytes); 1191fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (status == FwdLockConv_Status_SyntaxError) { 1192fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromConvertData.errorPos = pSession->numCharsConsumed; 1193fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1194fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1195fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 1196fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 1197fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 1198fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat DalbeheraFwdLockConv_Status_t FwdLockConv_CloseSession(int sessionId, FwdLockConv_Output_t *pOutput) { 1199fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 1200fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (!FwdLockConv_IsValidSession(sessionId) || pOutput == NULL) { 1201fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_InvalidArgument; 1202fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1203fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Session_t *pSession = sessionPtrs[sessionId]; 1204fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pOutput->fromConvertData.pBuffer); 1205fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pSession->parserState != FwdLockConv_ParserState_Done) { 1206fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromCloseSession.errorPos = pSession->numCharsConsumed; 1207fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_SyntaxError; 1208fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1209fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Finalize the data signature. 121090855078eb989944bca1824058d7231cd68e5021Henrik B Andersson unsigned int signatureSize = SHA1_HASH_SIZE; 1211fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Final(&pSession->signingContext, pOutput->fromCloseSession.signatures, 1212fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &signatureSize); 1213fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (signatureSize != SHA1_HASH_SIZE) { 1214fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 1215fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1216fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // Calculate the header signature, which is a signature of the rest of the header 1217fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera // including the data signature. 1218fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Init_ex(&pSession->signingContext, NULL, KEY_SIZE, NULL, NULL); 1219fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pSession->topHeader, TOP_HEADER_SIZE); 1220fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, (unsigned char *)pSession->contentType.ptr, 1221fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType.length); 1222fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pSession->pEncryptedSessionKey, 1223fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->encryptedSessionKeyLength); 1224fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_Update(&pSession->signingContext, pOutput->fromCloseSession.signatures, 122590855078eb989944bca1824058d7231cd68e5021Henrik B Andersson SHA1_HASH_SIZE); 122690855078eb989944bca1824058d7231cd68e5021Henrik B Andersson HMAC_Final(&pSession->signingContext, 122790855078eb989944bca1824058d7231cd68e5021Henrik B Andersson &pOutput->fromCloseSession.signatures[SHA1_HASH_SIZE], &signatureSize); 1228fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (signatureSize != SHA1_HASH_SIZE) { 1229fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_ProgramError; 1230fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1231fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromCloseSession.fileOffset = TOP_HEADER_SIZE + 1232fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pSession->contentType.length + pSession->encryptedSessionKeyLength; 1233fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OK; 1234fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1235fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1236fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera pOutput->fromCloseSession.errorPos = INVALID_OFFSET; 1237fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1238fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pSession->mimeHeaderName.ptr); 1239fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pSession->contentType.ptr); 1240fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pSession->pEncryptedSessionKey); 1241fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera HMAC_CTX_cleanup(&pSession->signingContext); 1242fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ReleaseSession(sessionId); 1243fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1244fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 1245fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 1246fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera 1247fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat DalbeheraFwdLockConv_Status_t FwdLockConv_ConvertOpenFile(int inputFileDesc, 1248fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_ReadFunc_t *fpReadFunc, 1249fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int outputFileDesc, 1250fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_WriteFunc_t *fpWriteFunc, 1251fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_LSeekFunc_t *fpLSeekFunc, 1252fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera off64_t *pErrorPos) { 1253fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t status; 1254fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pErrorPos != NULL) { 1255fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pErrorPos = INVALID_OFFSET; 1256fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1257fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (fpReadFunc == NULL || fpWriteFunc == NULL || fpLSeekFunc == NULL || inputFileDesc < 0 || 1258fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera outputFileDesc < 0) { 1259fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_InvalidArgument; 1260fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1261fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera char *pReadBuffer = malloc(READ_BUFFER_SIZE); 1262fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (pReadBuffer == NULL) { 1263fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_OutOfMemory; 1264fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1265fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera int sessionId; 1266fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Output_t output; 1267fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_OpenSession(&sessionId, &output); 1268fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 1269fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t numBytesRead; 1270fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FwdLockConv_Status_t closeStatus; 1271fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera while ((numBytesRead = 1272fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera fpReadFunc(inputFileDesc, pReadBuffer, READ_BUFFER_SIZE)) > 0) { 1273fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_ConvertData(sessionId, pReadBuffer, (size_t)numBytesRead, 1274fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera &output); 1275fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 1276fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (output.fromConvertData.pBuffer != NULL && 1277fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera output.fromConvertData.numBytes > 0) { 1278fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera ssize_t numBytesWritten = fpWriteFunc(outputFileDesc, 1279fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera output.fromConvertData.pBuffer, 1280fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera output.fromConvertData.numBytes); 1281fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (numBytesWritten != (ssize_t)output.fromConvertData.numBytes) { 1282fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_FileWriteError; 1283fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1284fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1285fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1286fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else { 1287fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) { 1288fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pErrorPos = output.fromConvertData.errorPos; 1289fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1290fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera break; 1291fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1292fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } // end while 1293fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (numBytesRead < 0) { 1294fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_FileReadError; 1295fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1296fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera closeStatus = FwdLockConv_CloseSession(sessionId, &output); 1297fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (status == FwdLockConv_Status_OK) { 1298fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (closeStatus != FwdLockConv_Status_OK) { 1299fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera if (closeStatus == FwdLockConv_Status_SyntaxError && pErrorPos != NULL) { 1300fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *pErrorPos = output.fromCloseSession.errorPos; 1301fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1302fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = closeStatus; 1303fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (fpLSeekFunc(outputFileDesc, output.fromCloseSession.fileOffset, 1304fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera SEEK_SET) < 0) { 1305fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_FileSeekError; 1306fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } else if (fpWriteFunc(outputFileDesc, output.fromCloseSession.signatures, 1307fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera FWD_LOCK_SIGNATURES_SIZE) != FWD_LOCK_SIGNATURES_SIZE) { 1308fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera status = FwdLockConv_Status_FileWriteError; 1309fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1310fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1311fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1312fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera free(pReadBuffer); 1313fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1314fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera } 1315fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera return status; 1316fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera} 1317