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