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 <errno.h>
19fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <fcntl.h>
20fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <pthread.h>
21fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <stdlib.h>
22fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <string.h>
23fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <sys/stat.h>
24fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <unistd.h>
25fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include <openssl/aes.h>
26fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
27fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#include "FwdLockGlue.h"
28fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
29fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define TRUE 1
30fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define FALSE 0
31fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
32fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define KEY_SIZE 16
33fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera#define KEY_SIZE_IN_BITS (KEY_SIZE * 8)
34fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
35fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int isInitialized = FALSE;
36fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
37fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic const char strKeyFilename[] = "/data/drm/fwdlock/kek.dat";
38fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
39fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic AES_KEY encryptionRoundKeys;
40fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic AES_KEY decryptionRoundKeys;
41fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
42fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/**
43fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Creates all directories along the fully qualified path of the given file.
44fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *
45fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] path A reference to the fully qualified path of a file.
46fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] mode The access mode to use for the directories being created.
47fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *
48fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the operation was successful.
49fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */
50fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockGlue_CreateDirectories(const char *path, mode_t mode) {
51fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    int result = TRUE;
52fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    size_t partialPathLength = strlen(path);
53fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    char *partialPath = malloc(partialPathLength + 1);
54fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    if (partialPath == NULL) {
55fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        result = FALSE;
56fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    } else {
57fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        size_t i;
58fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        for (i = 0; i < partialPathLength; ++i) {
59fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            if (path[i] == '/' && i > 0) {
60fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                partialPath[i] = '\0';
61fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                if (mkdir(partialPath, mode) != 0 && errno != EEXIST) {
62fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                    result = FALSE;
63fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                    break;
64fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                }
65fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            }
66fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            partialPath[i] = path[i];
67fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
68fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        free(partialPath);
69fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
70fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return result;
71fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
72fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
73fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/**
74fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Initializes the round keys used for encryption and decryption of session keys. First creates a
75fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * device-unique key-encryption key if none exists yet.
76fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */
77fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic void FwdLockGlue_InitializeRoundKeys() {
78fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    unsigned char keyEncryptionKey[KEY_SIZE];
79fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    int fileDesc = open(strKeyFilename, O_RDONLY);
80fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    if (fileDesc >= 0) {
81fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        if (read(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) {
82fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            isInitialized = TRUE;
83fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
84fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        (void)close(fileDesc);
85fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    } else if (errno == ENOENT &&
86fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera               FwdLockGlue_GetRandomNumber(keyEncryptionKey, KEY_SIZE) &&
87fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera               FwdLockGlue_CreateDirectories(strKeyFilename, S_IRWXU)) {
88fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        fileDesc = open(strKeyFilename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR);
89fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        if (fileDesc >= 0) {
90fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            if (write(fileDesc, keyEncryptionKey, KEY_SIZE) == KEY_SIZE) {
91fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                isInitialized = TRUE;
92fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            }
93fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            (void)close(fileDesc);
94fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
95fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
96fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    if (isInitialized) {
97fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        if (AES_set_encrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &encryptionRoundKeys) != 0 ||
98fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            AES_set_decrypt_key(keyEncryptionKey, KEY_SIZE_IN_BITS, &decryptionRoundKeys) != 0) {
99fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            isInitialized = FALSE;
100fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
101fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
102fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    memset(keyEncryptionKey, 0, KEY_SIZE); // Zero out key data.
103fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
104fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
105fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera/**
106fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * Validates the padding of a decrypted key.
107fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *
108fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] pData A reference to the buffer containing the decrypted key and padding.
109fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @param[in] decryptedKeyLength The length in bytes of the decrypted key.
110fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera *
111fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera * @return A Boolean value indicating whether the padding was valid.
112fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera */
113fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherastatic int FwdLockGlue_ValidatePadding(const unsigned char *pData, size_t decryptedKeyLength) {
114fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    size_t i;
115fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    size_t padding = AES_BLOCK_SIZE - (decryptedKeyLength % AES_BLOCK_SIZE);
116fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    pData += decryptedKeyLength;
117fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    for (i = 0; i < padding; ++i) {
118fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        if ((size_t)*pData != padding) {
119fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            return FALSE;
120fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
121fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        ++pData;
122fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
123fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return TRUE;
124fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
125fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
126fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockGlue_GetRandomNumber(void *pBuffer, size_t numBytes) {
127fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    // Generate 'cryptographically secure' random bytes by reading them from "/dev/urandom" (the
128fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    // non-blocking version of "/dev/random").
129fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    ssize_t numBytesRead = 0;
130fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    int fileDesc = open("/dev/urandom", O_RDONLY);
131fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    if (fileDesc >= 0) {
132fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        numBytesRead = read(fileDesc, pBuffer, numBytes);
133fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        (void)close(fileDesc);
134fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
135fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return numBytesRead >= 0 && (size_t)numBytesRead == numBytes;
136fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
137fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
138fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockGlue_InitializeKeyEncryption() {
139fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    static pthread_once_t once = PTHREAD_ONCE_INIT;
140fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    pthread_once(&once, FwdLockGlue_InitializeRoundKeys);
141fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return isInitialized;
142fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
143fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
144fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeherasize_t FwdLockGlue_GetEncryptedKeyLength(size_t plaintextKeyLength) {
145fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return ((plaintextKeyLength / AES_BLOCK_SIZE) + 2) * AES_BLOCK_SIZE;
146fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
147fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
148fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockGlue_EncryptKey(const void *pPlaintextKey,
149fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                           size_t plaintextKeyLength,
150fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                           void *pEncryptedKey,
151fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                           size_t encryptedKeyLength) {
152fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    int result = FALSE;
153fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(plaintextKeyLength));
154fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    if (FwdLockGlue_InitializeKeyEncryption()) {
155fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        unsigned char initVector[AES_BLOCK_SIZE];
156fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        if (FwdLockGlue_GetRandomNumber(initVector, AES_BLOCK_SIZE)) {
157fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            size_t padding = AES_BLOCK_SIZE - (plaintextKeyLength % AES_BLOCK_SIZE);
158fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE;
159fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            memcpy(pEncryptedKey, pPlaintextKey, plaintextKeyLength);
160fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            memset((unsigned char *)pEncryptedKey + plaintextKeyLength, (int)padding, padding);
161fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            memcpy((unsigned char *)pEncryptedKey + dataLength, initVector, AES_BLOCK_SIZE);
162fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            AES_cbc_encrypt(pEncryptedKey, pEncryptedKey, dataLength, &encryptionRoundKeys,
163fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                            initVector, AES_ENCRYPT);
164fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            result = TRUE;
165fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
166fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
167fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return result;
168fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
169fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera
170fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbeheraint FwdLockGlue_DecryptKey(const void *pEncryptedKey,
171fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                           size_t encryptedKeyLength,
172fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                           void *pDecryptedKey,
173fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                           size_t decryptedKeyLength) {
174fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    int result = FALSE;
175fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    assert(encryptedKeyLength == FwdLockGlue_GetEncryptedKeyLength(decryptedKeyLength));
176fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    if (FwdLockGlue_InitializeKeyEncryption()) {
177fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        size_t dataLength = encryptedKeyLength - AES_BLOCK_SIZE;
178fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        unsigned char *pData = malloc(dataLength);
179fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        if (pData != NULL) {
180fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            unsigned char initVector[AES_BLOCK_SIZE];
181fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            memcpy(pData, pEncryptedKey, dataLength);
182fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            memcpy(initVector, (const unsigned char *)pEncryptedKey + dataLength, AES_BLOCK_SIZE);
183fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            AES_cbc_encrypt(pData, pData, dataLength, &decryptionRoundKeys, initVector,
184fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera                            AES_DECRYPT);
185fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            memcpy(pDecryptedKey, pData, decryptedKeyLength);
186fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            result = FwdLockGlue_ValidatePadding(pData, decryptedKeyLength);
187fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera            free(pData);
188fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera        }
189fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    }
190fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera    return result;
191fdd65a0fc7df2c878cc601e4c0f4021cb264f051Pravat Dalbehera}
192