File: MetadataValueStretchKey.cpp

package info (click to toggle)
sleuthkit 4.14.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,268 kB
  • sloc: ansic: 143,839; cpp: 54,644; java: 39,009; xml: 2,417; python: 1,085; perl: 874; makefile: 451; sh: 196
file content (111 lines) | stat: -rw-r--r-- 4,738 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
 ** The Sleuth Kit
 **
 ** Brian Carrier [carrier <at> sleuthkit [dot] org]
 ** Copyright (c) 2024 Sleuth Kit Labs, LLC. All Rights reserved
 ** Copyright (c) 2010-2021 Brian Carrier.  All Rights reserved
 **
 ** This software is distributed under the Common Public License 1.0
 */

#ifdef HAVE_LIBMBEDTLS

#include "MetadataValueStretchKey.h"

#include "mbedtls/sha256.h" 

MetadataValueStretchKey::MetadataValueStretchKey(BITLOCKER_METADATA_VALUE_TYPE valueType, uint8_t* buf, size_t bufLen) : MetadataValue(valueType) {

    if (bufLen < m_headerLen) {
        registerError("MetadataValueStretchKey::MetadataValueStretchKey(): Buffer for creating MetadataValueStretchKey was too short");
        memset(m_salt, 0, 16);
        return;
    }

    m_encryptionType = getEncryptionTypeEnum(tsk_getu16(TSK_LIT_ENDIAN, &(buf[0])));
    memcpy(m_salt, &(buf[4]), 16);

    m_encryptedKeyEntry = MetadataEntry::createMetadataEntry(&(buf[m_headerLen]), bufLen - m_headerLen);
}

/**
* Parse the stetch key entry and generate the stretched key from the given password hash.
* 
* @param passwordHash     Previously computed hash of the password/recovery password
* @param passwordHashLen  Length of the password hash
* @param stretchKey       Stretched key will be stored here (should be allocated)
* @param stretchKeyLen    Length of the stretchKey buffer (expected to be BITLOCKER_STRETCH_KEY_SHA256_LEN)
* 
* @return SUCCESS on success, GENERAL_ERROR if an error occurs
*/
BITLOCKER_STATUS MetadataValueStretchKey::parseStretchKeyUsingPassword(uint8_t* passwordHash, size_t passwordHashLen, uint8_t* stretchKey, size_t stretchKeyLen) {

    // Generate stretch key
    if (stretchKeyLen != BITLOCKER_STRETCH_KEY_SHA256_LEN) {
        registerError("MetadataValueStretchKey::parseStretchKeyUsingPassword: Incorrect stretch key length");
        return BITLOCKER_STATUS::GENERAL_ERROR;
    }

    if (BITLOCKER_STATUS::SUCCESS != generateStretchedKey(passwordHash, passwordHashLen, m_salt, 16, stretchKey, BITLOCKER_STRETCH_KEY_SHA256_LEN)) {
        return BITLOCKER_STATUS::GENERAL_ERROR;
    }
    writeDebug("MetadataValueStretchKey::parseStretchKeyUsingPassword Stretched key: " + convertByteArrayToString(stretchKey, BITLOCKER_STRETCH_KEY_SHA256_LEN));

    // There's an encrypted key entry in here but it's unclear how to decrypt it. Ignore for now.
    return BITLOCKER_STATUS::SUCCESS;
}

/**
* Generate stretched key from password hash
* 
* @param passwordHash     Previously computed hash of the password/recovery password
* @param passwordHashLen  Length of the password hash (should be BITLOCKER_STRETCH_KEY_SHA256_LEN)
* @param salt             The salt from the stretch key entry
* @param saltLen          Length of the salt (should be BITLOCKER_STRETCH_KEY_SALT_LEN)
* @param result           Stretched key will be stored here
* @param resultLen        Length of the result buffer (should be BITLOCKER_STRETCH_KEY_SHA256_LEN)
* 
* @return SUCCESS on success, GENERAL_ERROR if an error occurs
*/
BITLOCKER_STATUS MetadataValueStretchKey::generateStretchedKey(uint8_t* passwordHash, size_t passwordHashLen, uint8_t* salt, size_t saltLen, uint8_t* result, size_t resultLen) {

    if (passwordHashLen != BITLOCKER_STRETCH_KEY_SHA256_LEN
        || saltLen != BITLOCKER_STRETCH_KEY_SALT_LEN
        || resultLen != BITLOCKER_STRETCH_KEY_SHA256_LEN) {
        writeError("MetadataValueStretchKey::generateStretchedKey: Incorrect buffer length(s)");
        return BITLOCKER_STATUS::GENERAL_ERROR;
    }

    writeDebug("MetadataValueStretchKey::generateStretchedKey: PasswordHash: " + convertByteArrayToString(passwordHash, passwordHashLen));
    writeDebug("MetadataValueStretchKey::generateStretchedKey: Salt:         " + convertByteArrayToString(salt, saltLen));

    struct {
        uint8_t updatedHash[BITLOCKER_STRETCH_KEY_SHA256_LEN];
        uint8_t passwordHash[BITLOCKER_STRETCH_KEY_SHA256_LEN];
        uint8_t salt[BITLOCKER_STRETCH_KEY_SALT_LEN];
        uint64_t hashCount;
    } hashStruct;

    size_t structSize = sizeof(hashStruct);
    memset(&hashStruct, 0, structSize);
    memcpy(hashStruct.passwordHash, passwordHash, BITLOCKER_STRETCH_KEY_SHA256_LEN);
    memcpy(hashStruct.salt, salt, BITLOCKER_STRETCH_KEY_SALT_LEN);

    for (uint32_t i = 0; i < 0x100000; ++i) {
        mbedtls_sha256((unsigned char*)(&hashStruct), structSize, hashStruct.updatedHash, 0);
        hashStruct.hashCount++;
    }

    memcpy(result, hashStruct.updatedHash, BITLOCKER_STRETCH_KEY_SHA256_LEN);
    memset(&hashStruct, 0, structSize);

    return BITLOCKER_STATUS::SUCCESS;
}

MetadataValueStretchKey::~MetadataValueStretchKey() {
    if (m_encryptedKeyEntry != NULL) {
        delete m_encryptedKeyEntry;
    }
}

#endif