PDOS

[uia] / trunk / uia / netsteria / pass.cc  

View of /trunk/uia/netsteria/pass.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4768 - (download) (as text) (annotate)
Thu Sep 24 16:51:39 2009 UTC (2 months ago) by baford
File size: 2554 byte(s)
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