![]()
Parent Directory
|
Revision Log
straggler from 1-Feb-06
// Journal password entrypoint chunks (passchunks)
#include <inttypes.h>
#include <assert.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include "sha2.h"
#define MAXPASSCHUNK 1024
struct passchunk {
uint32_t iv[4]; // Initialization Vector for CBC-mode AES
uint32_t chk[4]; // Password check block
uint64_t roothash[8]; // SHA-512 outer hash of root chunk
uint64_t rootkey[4]; // AES-256 decryption key for root chunk
};
// Takes username and password in UTF-8,
// and generates a 256-bit AES encryption key from it.
static void passkey(const char *username, const char *password, AES_KEY *key)
{
SHA384_CTX ctx;
SHA384_Init(&ctx);
static char magic[] = "UIPjournalPasswd"; // 16 bytes
SHA384_Update(&ctx, magic, 16);
SHA384_Update(&ctx, username, strlen(username)+1);
SHA384_Update(&ctx, password, strlen(password)+1);
uint64_t hash[8];
SHA384_Final((uint8_t*)hash, &ctx);
AES_set_encrypt_key(((uint8_t*)hash, 256, key);
}
// Encrypt a passchunk in-place, using CBC mode with random IV.
// Everything but the IV and CHK block must already be filled in.
// The passchunk length must be a multiple of 16, the AES block length.
void encpass(void *chunk, size_t len, const AES_KEY *key)
{
assert(len >= sizeof(struct passchunk));
assert(len <= MAXPASSCHUNK);
assert((len & 15) == 0);
// Initialize the IV
int rc = RAND_bytes(chunk, 16);
assert(rc != 0); // XX
// Initialie the check block
memcpy(chunk+16, "UIPjournalRecord", 16);
// CBC-encrypt the whole passchunk.
AES_cbc_encrypt(chunk+16, chunk+16, len-16, key, chunk, 1);
}
// Check the first 32 bytes of a possible passchunk
// to see if it looks right after being decrypted with a given key.
// Does not modify the chunk header buffer provided.
// Returns nonzero if the header decrypts correctly, zero otherwise.
int checkpass(const void *chunkhdr, const AES_KEY *key)
{
uint8_t result[16];
AES_cbc_encrypt(chunkhdr+16, result, 16, key, chunkhdr, 0);
return memcmp(result, "UIPjournalRecord", 16) == 0;
}
// Decrypt a complete passchunk in-place.
// Returns nonzero if the decrypted passchunk looks valid, zero if not.
int decpass(void *chunk, size_t len, const AES_KEY *key)
{
assert(len >= sizeof(struct passchunk));
assert(len <= MAXPASSCHUNK);
assert((len & 15) == 0);
// Decrypt the chunk
AES_cbc_encrypt(chunk+16, chunk+16, len-16, key, chunk, 0);
// Check the header and tailer records
if (memcmp(chunk+16, "UIPjournalRecord", 16) != 0)
return 0;
if (memcmp(chunk+len-16, "UIPjournalTailer", 16) != 0)
return 0;
return 1;
}
| Maintained by PDOS | ViewVC Help |
| Powered by ViewVC 1.0.3 |