From bb3c2172b8140fd2d09505a58a3d2dfe89f6ad02 Mon Sep 17 00:00:00 2001 From: antona Date: Wed, 27 Jul 2005 10:30:57 +0000 Subject: [PATCH] Run through Lindent and some manual aftercleanups. --- ntfsprogs/decrypt.c | 444 ++++++++++++++++++---------------------- ntfsprogs/decrypt.h | 22 +- ntfsprogs/ntfsdecrypt.c | 218 ++++++++++---------- 3 files changed, 315 insertions(+), 369 deletions(-) diff --git a/ntfsprogs/decrypt.c b/ntfsprogs/decrypt.c index a29066e4..467a737e 100644 --- a/ntfsprogs/decrypt.c +++ b/ntfsprogs/decrypt.c @@ -1,11 +1,9 @@ /* - * decrypt.c - Part of the Linux-NTFS project. + * decrypt.c - $EFS decryption routined. Part of the Linux-NTFS project. * * Copyright (c) 2005 Yuval Fledel * Copyright (c) 2005 Anton Altaparmakov * - * $EFS decryption routines. - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -32,7 +30,6 @@ #include "decrypt.h" #ifdef __CYGWIN__ -//#define USE_CRYPTOAPI_RSA 1 #define _WIN32_WINNT 0x501 #define WINVER 0x501 @@ -52,19 +49,19 @@ #define CRYPT_ACQUIRE_CACHE_FLAG 1 #endif -/* windows 2k+ imports */ -typedef BOOL (WINAPI *LPFN_CryptAcquireCertificatePrivateKey) (PCCERT_CONTEXT, - DWORD, void *, HCRYPTPROV *, DWORD *, BOOL*); -typedef BOOL (WINAPI *LPFN_CertCloseStore) (HCERTSTORE, DWORD); -typedef PCCERT_CONTEXT (WINAPI *LPFN_CertFindCertificateInStore) (HCERTSTORE, - DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT); -typedef BOOL (WINAPI *LPFN_CertFreeCertificateContext) (PCCERT_CONTEXT); -typedef HCERTSTORE (WINAPI *LPFN_CertOpenStore) (LPCSTR, DWORD, HCRYPTPROV, - DWORD, const void*); +/* Windows 2k+ imports. */ +typedef BOOL(WINAPI *LPFN_CryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT, + DWORD, void *, HCRYPTPROV *, DWORD *, BOOL *); +typedef BOOL(WINAPI *LPFN_CertCloseStore)(HCERTSTORE, DWORD); +typedef PCCERT_CONTEXT(WINAPI *LPFN_CertFindCertificateInStore)(HCERTSTORE, + DWORD, DWORD, DWORD, const void *, PCCERT_CONTEXT); +typedef BOOL(WINAPI *LPFN_CertFreeCertificateContext)(PCCERT_CONTEXT); +typedef HCERTSTORE(WINAPI *LPFN_CertOpenStore)(LPCSTR, DWORD, HCRYPTPROV, + DWORD, const void *); // NT4SP3+ WINME or 95+ w/ IE5+ -static LPFN_CryptAcquireCertificatePrivateKey - fnCryptAcquireCertificatePrivateKey; +static LPFN_CryptAcquireCertificatePrivateKey + fnCryptAcquireCertificatePrivateKey; // osr2+ NT4SP3+ or NT4 w/ IE3.02: static LPFN_CertCloseStore fnCertCloseStore; static LPFN_CertFindCertificateInStore fnCertFindCertificateInStore; @@ -74,7 +71,7 @@ static LPFN_CertOpenStore fnCertOpenStore; /* global variable: handle to crypt32.dll */ static HMODULE hCrypt32 = INVALID_HANDLE_VALUE; -#else /* defined(__CYGWIN__) */ +#else /* !defined(__CYGWIN__) */ #include #include @@ -84,7 +81,7 @@ static HMODULE hCrypt32 = INVALID_HANDLE_VALUE; #define CALG_DESX (0x6604) #define CALG_AES_256 (0x6610) -#endif /* defined(__CYGWIN__) */ +#endif /* !defined(__CYGWIN__) */ /* This must be after windows.h include. */ #include "types.h" @@ -92,25 +89,22 @@ static HMODULE hCrypt32 = INVALID_HANDLE_VALUE; typedef struct { #ifdef __CYGWIN__ HCERTSTORE hSystemStore; -#else - int nothing; /* unused */ -#endif /* defined(__CYGWIN__) */ +#else /* !defined(__CYGWIN__) */ + int nothing; /* unused */ +#endif /* !defined(__CYGWIN__) */ } DECRYPT_SESSION; typedef struct { u64 desx_key[3]; u8 *key_data; u32 alg_id; - gcry_cipher_hd_t gcry_cipher_hd; // handle to the decrypted FEK. - gcry_sexp_t sexp_key; // the user's RSA key. -#ifdef USE_CRYPTOAPI_RSA - HCRYPTKEY hCryptKey; -#endif /* defined(__CYGWIN__) */ + gcry_cipher_hd_t gcry_cipher_hd; + gcry_sexp_t sexp_key; // the user's RSA key. } DECRYPT_KEY; /* DESX-MS128 implementation for libgcrypt. */ -static gcry_module_t desx_module; -static int desx_algorithm_id = -1; +static gcry_module_t desx_module; +static int desx_algorithm_id = -1; typedef struct desx_ctx { gcry_cipher_hd_t gcry_cipher_hd; @@ -152,13 +146,13 @@ static void desx_key_expand(const u8 *src, u8 *in_whitening, u8 *out_whitening, MD5_Update(&ctx2, salt2, salt_len); MD5_Final(md, &ctx2); memcpy(out_whitening, md, 8); - memcpy(in_whitening, md+8, 8); + memcpy(in_whitening, md + 8, 8); } static gcry_err_code_t do_desx_setkey(void *context, const u8 *key, unsigned keylen) { - struct desx_ctx *ctx = (desx_ctx *)context; + struct desx_ctx *ctx = (desx_ctx*)context; gcry_error_t err; u8 des_key[8]; @@ -166,89 +160,73 @@ static gcry_err_code_t do_desx_setkey(void *context, const u8 *key, fprintf(stderr, "not 16\n"); return GPG_ERR_INV_KEYLEN; } - if ((err = gcry_cipher_open(&ctx->gcry_cipher_hd, GCRY_CIPHER_DES, - GCRY_CIPHER_MODE_ECB, 0)) != GPG_ERR_NO_ERROR) + GCRY_CIPHER_MODE_ECB, 0)) != GPG_ERR_NO_ERROR) return err; - - if ((err = gcry_cipher_reset(ctx->gcry_cipher_hd))) { + if ((err = gcry_cipher_reset(ctx->gcry_cipher_hd))) fprintf(stderr, "err is %u.\n", err); - } - desx_key_expand(key, ctx->in_whitening, ctx->out_whitening, des_key); - -/* +#if 0 fprintf(stderr, "expanded keys (hex) =\n\t0x%llx (des)\n\t" "0x%llx (in-whitening)\n\t" "0x%llx (out-whitening)\n", *(u64*)des_key, *(u64*)ctx->in_whitening, *(u64*)ctx->out_whitening); -*/ - +#endif if ((err = gcry_cipher_setkey(ctx->gcry_cipher_hd, des_key, 8))) { fprintf(stderr, "do_desx_setkey: error %u.\n", err); // TODO: destroy gcry_cipher_hd } - return GPG_ERR_NO_ERROR; } static void do_desx_decrypt(void *context, u8 *outbuf, const u8 *inbuf) { - struct desx_ctx *ctx = (desx_ctx *)context; + struct desx_ctx *ctx = (desx_ctx*)context; gcry_error_t err; u8 buf[8]; - *((unsigned long long *)buf) = *((const unsigned long long *)inbuf) - ^ *(const unsigned long long *)ctx->out_whitening; - - if ((err = gcry_cipher_encrypt(ctx->gcry_cipher_hd, - outbuf, 8, buf, 8))) { + *((u64*)buf) = *((const u64*)inbuf) ^ *(const u64*)ctx->out_whitening; + if ((err = gcry_cipher_encrypt(ctx->gcry_cipher_hd, outbuf, 8, buf, 8))) fprintf(stderr, "desx decryption failed: %u.\n", err); - } - - *((unsigned long long *)outbuf) ^= *(const unsigned long long *) - ctx->in_whitening; + *((u64*)outbuf) ^= *(const u64*)ctx->in_whitening; } static gcry_cipher_spec_t cipher = { .name = "DES-X-MS128", .blocksize = 8, .keylen = 128, - .contextsize = sizeof (struct desx_ctx), + .contextsize = sizeof(struct desx_ctx), .setkey = do_desx_setkey, .decrypt = do_desx_decrypt, }; #ifdef __CYGWIN__ - static int cryptoAPI_init_imports(void) { if (hCrypt32 == INVALID_HANDLE_VALUE) hCrypt32 = LoadLibrary("crypt32.dll"); - if (!fnCryptAcquireCertificatePrivateKey) - fnCryptAcquireCertificatePrivateKey = - (LPFN_CryptAcquireCertificatePrivateKey) - GetProcAddress(hCrypt32, - "CryptAcquireCertificatePrivateKey"); + fnCryptAcquireCertificatePrivateKey = + (LPFN_CryptAcquireCertificatePrivateKey) + GetProcAddress(hCrypt32, + "CryptAcquireCertificatePrivateKey"); if (!fnCertCloseStore) fnCertCloseStore = (LPFN_CertCloseStore) - GetProcAddress(hCrypt32, "CertCloseStore"); + GetProcAddress(hCrypt32, "CertCloseStore"); if (!fnCertFindCertificateInStore) - fnCertFindCertificateInStore = - (LPFN_CertFindCertificateInStore) - GetProcAddress(hCrypt32, "CertFindCertificateInStore"); + fnCertFindCertificateInStore = (LPFN_CertFindCertificateInStore) + GetProcAddress(hCrypt32, + "CertFindCertificateInStore"); if (!fnCertFreeCertificateContext) - fnCertFreeCertificateContext = - (LPFN_CertFreeCertificateContext) - GetProcAddress(hCrypt32, "CertFreeCertificateContext"); + fnCertFreeCertificateContext = (LPFN_CertFreeCertificateContext) + GetProcAddress(hCrypt32, + "CertFreeCertificateContext"); if (!fnCertOpenStore) - fnCertOpenStore = (LPFN_CertOpenStore) - GetProcAddress(hCrypt32, "CertOpenStore"); - + fnCertOpenStore = (LPFN_CertOpenStore)GetProcAddress(hCrypt32, + "CertOpenStore"); return fnCryptAcquireCertificatePrivateKey && fnCertCloseStore && - fnCertFindCertificateInStore && - fnCertFreeCertificateContext && fnCertOpenStore; + fnCertFindCertificateInStore && fnCertFreeCertificateContext && + fnCertOpenStore; } #endif /* defined(__CYGWIN__) */ @@ -256,14 +234,17 @@ static int cryptoAPI_init_imports(void) #ifdef DO_CRYPTO_TESTS /* Do not remove this test code from this file! AIA */ -static BOOL desx_key_expand_test(void) { +static BOOL desx_key_expand_test(void) +{ const u8 known_desx_on_disk_key[16] = { - 0xa1, 0xf9, 0xe0, 0xb2, 0x53, 0x23, 0x9e, 0x8f, - 0x0f, 0x91, 0x45, 0xd9, 0x8e, 0x20, 0xec, 0x30 }; + 0xa1, 0xf9, 0xe0, 0xb2, 0x53, 0x23, 0x9e, 0x8f, + 0x0f, 0x91, 0x45, 0xd9, 0x8e, 0x20, 0xec, 0x30 + }; const u8 known_desx_expanded_key[24] = { - 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f, - 0xed, 0xda, 0x4c, 0x47, 0x60, 0x49, 0xdb, 0x8d, - 0x75, 0xf6, 0xa0, 0x1a, 0xc0, 0xca, 0x28, 0x1e }; + 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f, + 0xed, 0xda, 0x4c, 0x47, 0x60, 0x49, 0xdb, 0x8d, + 0x75, 0xf6, 0xa0, 0x1a, 0xc0, 0xca, 0x28, 0x1e + }; u8 test_desx_expanded_key[24]; int res; @@ -271,17 +252,21 @@ static BOOL desx_key_expand_test(void) { res = !memcmp(test_desx_expanded_key, known_desx_expanded_key, sizeof(known_desx_expanded_key)); fprintf(stderr, "Testing whether desx_key_expand() works: %s\n", - res ? "SUCCESS" : "FAILED"); + res ? "SUCCESS" : "FAILED"); return res; } -static BOOL des_test(void) { +static BOOL des_test(void) +{ const u8 known_des_key[8] = { - 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f }; + 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f + }; const u8 known_des_encrypted_data[8] = { - 0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f }; + 0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f + }; const u8 known_decrypted_data[8] = { - 0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09 }; + 0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09 + }; u8 test_decrypted_data[8]; int res; gcry_error_t gcry_error2; @@ -293,8 +278,8 @@ static BOOL des_test(void) { "%u).\n", gcry_error2); return FALSE; } - if ((gcry_error2 = gcry_cipher_setkey(gcry_cipher_hd, - known_des_key, sizeof(known_des_key)))) { + if ((gcry_error2 = gcry_cipher_setkey(gcry_cipher_hd, known_des_key, + sizeof(known_des_key)))) { fprintf(stderr, "Failed to set des key (gcry_error2 is %u).\n", gcry_error2); gcry_cipher_close(gcry_cipher_hd); @@ -302,10 +287,11 @@ static BOOL des_test(void) { } memcpy(test_decrypted_data, known_des_encrypted_data, sizeof(known_des_encrypted_data)); - /* Apply DES decyption. */ - gcry_error2 = gcry_cipher_decrypt(gcry_cipher_hd, - test_decrypted_data, sizeof(test_decrypted_data), - NULL, 0); + /* + * Apply DES decyption (ntfs actually uses encryption when decrypting). + */ + gcry_error2 = gcry_cipher_encrypt(gcry_cipher_hd, test_decrypted_data, + sizeof(test_decrypted_data), NULL, 0); gcry_cipher_close(gcry_cipher_hd); if (gcry_error2) { fprintf(stderr, "Failed to des decrypt test data (gcry_error2 " @@ -315,27 +301,30 @@ static BOOL des_test(void) { res = !memcmp(test_decrypted_data, known_decrypted_data, sizeof(known_decrypted_data)); fprintf(stderr, "Testing whether des decryption works: %s\n", - res ? "SUCCESS" : "FAILED"); + res ? "SUCCESS" : "FAILED"); return res; } -#else +#else /* !defined(DO_CRYPTO_TESTS) */ -static inline BOOL desx_key_expand_test(void) { +static inline BOOL desx_key_expand_test(void) +{ return TRUE; } -static inline BOOL des_test(void) { +static inline BOOL des_test(void) +{ return TRUE; } -#endif +#endif /* !defined(DO_CRYPTO_TESTS) */ -decrypt_session *decrypt_open(void) { +decrypt_session *decrypt_open(void) +{ decrypt_session *session; /* TODO: refcount 'module' */ - if (desx_algorithm_id==-1) { + if (desx_algorithm_id == -1) { if (!desx_key_expand_test()) return NULL; if (!des_test()) @@ -344,7 +333,6 @@ decrypt_session *decrypt_open(void) { &desx_module)) return NULL; } - //fprintf(stderr, "desx_algorithm_id: %d\n", desx_algorithm_id); gcry_control(GCRYCTL_DISABLE_SECMEM, 0); @@ -358,49 +346,50 @@ decrypt_session *decrypt_open(void) { return NULL; } - if (!(hSystemStore = fnCertOpenStore(((LPCSTR)CERT_STORE_PROV_SYSTEM), - 0, (HCRYPTPROV)NULL, CERT_SYSTEM_STORE_CURRENT_USER, + if (!(hSystemStore = fnCertOpenStore(((LPCSTR) CERT_STORE_PROV_SYSTEM), + 0, (HCRYPTPROV) NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY"))) { fprintf(stderr, "Could not open system store.\n"); errno = -1; return NULL; } #endif /* defined(__CYGWIN__) */ - - session = (decrypt_session *)malloc(sizeof(DECRYPT_SESSION)); + session = (decrypt_session*)malloc(sizeof(DECRYPT_SESSION)); #ifdef __CYGWIN__ ((DECRYPT_SESSION *)session)->hSystemStore = hSystemStore; #endif /* defined(__CYGWIN__) */ return session; } -void decrypt_close(decrypt_session *session) { +void decrypt_close(decrypt_session *session) +{ #ifdef __CYGWIN__ - if (((DECRYPT_SESSION *)session)->hSystemStore) - fnCertCloseStore(((DECRYPT_SESSION *)session)->hSystemStore, - CERT_CLOSE_STORE_CHECK_FLAG); + if (((DECRYPT_SESSION*)session)->hSystemStore) + fnCertCloseStore(((DECRYPT_SESSION*)session)->hSystemStore, + CERT_CLOSE_STORE_CHECK_FLAG); /* fixme: racy */ FreeLibrary(hCrypt32); hCrypt32 = INVALID_HANDLE_VALUE; #endif /* defined(__CYGWIN__) */ - free(session); } -static inline void reverse_buffer(unsigned char *buf, unsigned int buf_size) { - unsigned char t; - unsigned int i; +static inline void reverse_buffer(unsigned char *buf, unsigned int buf_size) +{ + unsigned char t; + unsigned int i; - for (i=0; ihSystemStore, - (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), - 0, CERT_FIND_HASH, &hash_blob, NULL))) { - fprintf(stderr, "Could not find cert in store.\n"); - goto decrypt_key_open_err; - } - - dwKeySpec = AT_KEYEXCHANGE; - if (!fnCryptAcquireCertificatePrivateKey(pCert, - CRYPT_ACQUIRE_CACHE_FLAG, NULL, - &hCryptProv, &dwKeySpec, - &fCallerFreeProv)) { - fprintf(stderr, "Could not aquire private key from cert.\n"); - goto decrypt_key_open_err; - } - - if (!CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hCryptKey)) { - fprintf(stderr, "Could not aquire user key.\n"); - goto decrypt_key_open_err; - } - - key_size = sizeof(key_blob); - if (!CryptExportKey(hCryptKey, 0, PRIVATEKEYBLOB, 0, key_blob, &key_size)) { - fprintf(stderr, "Could not export key: Error 0x%x\n", - (unsigned int)GetLastError()); - errno = -1; - return NULL; - } - - if (!(key = (decrypt_key *)malloc(sizeof(DECRYPT_KEY)))) - goto decrypt_key_open_err; - -#ifdef USE_CRYPTOAPI_RSA - ((DECRYPT_KEY *)key)->hCryptKey = hCryptKey; -#else - RSAPUBKEY *rsa_pub_key = (RSAPUBKEY *)(key_blob + sizeof(PUBLICKEYSTRUC)); + RSAPUBKEY *rsa_pub_key; gcry_ac_handle_t gcry_handle; unsigned char *mpi_data; - gcry_mpi_t n,e,d,p,q,u; + gcry_mpi_t n, e, d, p, q, u; gcry_sexp_t sexp_key; gcry_error_t err; size_t size; int rc; - CryptDestroyKey(hCryptKey); + hash_blob.cbData = thumb_size; + hash_blob.pbData = thumb_print; + if (!(pCert = fnCertFindCertificateInStore( + ((DECRYPT_SESSION*)session)->hSystemStore, + (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), 0, + CERT_FIND_HASH, &hash_blob, NULL))) { + fprintf(stderr, "Could not find cert in store.\n"); + goto decrypt_key_open_err; + } + dwKeySpec = AT_KEYEXCHANGE; + if (!fnCryptAcquireCertificatePrivateKey(pCert, + CRYPT_ACQUIRE_CACHE_FLAG, NULL, &hCryptProv, + &dwKeySpec, &fCallerFreeProv)) { + fprintf(stderr, "Could not aquire private key from cert.\n"); + goto decrypt_key_open_err; + } + if (!CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hCryptKey)) { + fprintf(stderr, "Could not aquire user key.\n"); + goto decrypt_key_open_err; + } + key_size = sizeof(key_blob); + if (!CryptExportKey(hCryptKey, 0, PRIVATEKEYBLOB, 0, key_blob, + &key_size)) { + fprintf(stderr, "Could not export key: Error 0x%x\n", + (unsigned int)GetLastError()); + errno = -1; + return NULL; + } + if (!(key = (decrypt_key*)malloc(sizeof(DECRYPT_KEY)))) + goto decrypt_key_open_err; + CryptDestroyKey(hCryptKey); + rsa_pub_key = (RSAPUBKEY*)(key_blob + sizeof(PUBLICKEYSTRUC)); if ((err = gcry_ac_open(&gcry_handle, GCRY_AC_RSA, 0))) { fprintf(stderr, "Could not init gcrypt handle\n"); errno = -1; return NULL; } - e = gcry_mpi_set_ui(NULL, rsa_pub_key->pubexp); - mpi_data = (key_blob + 0x14); size = rsa_pub_key->bitlen / 8; reverse_buffer(mpi_data, size); - if ((rc = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, mpi_data, size, &size))) { + if ((rc = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, mpi_data, size, &size))) fprintf(stderr, "error scanning n.\n"); - } - mpi_data += (rsa_pub_key->bitlen / 8); size = rsa_pub_key->bitlen / 16; reverse_buffer(mpi_data, size); - if ((rc = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, mpi_data, size, &size))) { + if ((rc = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, mpi_data, size, &size))) fprintf(stderr, "error scanning p.\n"); - } - mpi_data += (rsa_pub_key->bitlen / 16); size = rsa_pub_key->bitlen / 16; reverse_buffer(mpi_data, size); - if ((rc = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, mpi_data, size, &size))) { + if ((rc = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, mpi_data, size, &size))) fprintf(stderr, "error scanning q.\n"); - } - - mpi_data += (rsa_pub_key->bitlen / 16)*3; + mpi_data += (rsa_pub_key->bitlen / 16) * 3; size = rsa_pub_key->bitlen / 16; reverse_buffer(mpi_data, size); - if ((rc = gcry_mpi_scan(&u, GCRYMPI_FMT_USG, mpi_data, size, &size))) { + if ((rc = gcry_mpi_scan(&u, GCRYMPI_FMT_USG, mpi_data, size, &size))) fprintf(stderr, "error scanning u.\n"); - } mpi_data += (rsa_pub_key->bitlen / 16); size = rsa_pub_key->bitlen / 8; reverse_buffer(mpi_data, size); - if ((rc = gcry_mpi_scan(&d, GCRYMPI_FMT_USG, mpi_data, size, &size))) { + if ((rc = gcry_mpi_scan(&d, GCRYMPI_FMT_USG, mpi_data, size, &size))) fprintf(stderr, "error scanning d.\n"); - } - - if ((rc = gcry_sexp_build(&sexp_key, NULL, - "(private-key (rsa (n %m) (e %m) (d %m) (p %m) (q %m) (u %m)))", - n, e, d, p, q, u))) { - fprintf(stderr, "Could build sexp from data, (error = 0x%x)\n", rc); + if ((rc = gcry_sexp_build(&sexp_key, NULL, "(private-key (rsa (n %m) " + "(e %m) (d %m) (p %m) (q %m) (u %m)))", n, e, d, p, q, + u))) { + fprintf(stderr, "Could build sexp from data, (error = 0x%x)\n", + rc); errno = -1; return FALSE; } - - ((DECRYPT_KEY *)key)->sexp_key = sexp_key; - + ((DECRYPT_KEY*)key)->sexp_key = sexp_key; // todo: release all -#endif return key; - -decrypt_key_open_err: - +decrypt_key_open_err: if (hCryptKey) CryptDestroyKey(hCryptKey); if (pCert) @@ -530,11 +495,11 @@ decrypt_key_open_err: return NULL; } -void decrypt_user_key_close(decrypt_key *key) { - DECRYPT_KEY *dkey = (DECRYPT_KEY *)key; +void decrypt_user_key_close(decrypt_key *key) +{ + DECRYPT_KEY *dkey = (DECRYPT_KEY*)key; if (dkey->gcry_cipher_hd) gcry_cipher_close(dkey->gcry_cipher_hd); - free(key); } @@ -543,20 +508,9 @@ void decrypt_user_key_close(decrypt_key *key) { * * warning: decrypting into the input buffer! */ -unsigned int decrypt_decrypt(decrypt_key *key, unsigned int data_size, - unsigned char *data) +unsigned int decrypt_decrypt(decrypt_key *key, unsigned int data_size, + unsigned char *data) { -#ifdef USE_CRYPTOAPI_RSA - DWORD size = data_size; - - if (!CryptDecrypt(((DECRYPT_KEY *)key)->hCryptKey, 0, - TRUE, 0, data, &size)) { - errno = -1; - return 0; - } - - return size; -#else gcry_sexp_t sexp_plain_data, sexp_enc_data; gcry_ac_handle_t gcry_handle; gcry_mpi_t mpi_buf; @@ -570,79 +524,74 @@ unsigned int decrypt_decrypt(decrypt_key *key, unsigned int data_size, errno = -1; return FALSE; } - - if ((rc = gcry_ac_data_new(&in))) { + if ((rc = gcry_ac_data_new(&in))) fprintf(stderr, "error allocating 'in'.\n"); - } reverse_buffer(data, data_size); size = data_size; - if ((rc = gcry_mpi_scan(&mpi_buf, GCRYMPI_FMT_USG, data, (size_t)data_size, &size))) { + if ((rc = gcry_mpi_scan(&mpi_buf, GCRYMPI_FMT_USG, data, + (size_t)data_size, &size))) fprintf(stderr, "error scanning 'in'.\n"); - } - - if ((rc = gcry_sexp_build(&sexp_enc_data, &size, "(enc-val (flags) (rsa (a %m)))", mpi_buf))) { - fprintf(stderr, "Could build sexp from data, (error = 0x%x)\n", rc); + if ((rc = gcry_sexp_build(&sexp_enc_data, &size, "(enc-val (flags) " + "(rsa (a %m)))", mpi_buf))) { + fprintf(stderr, "Could build sexp from data, (error = 0x%x)\n", + rc); errno = -1; return FALSE; } - - if ((rc = gcry_pk_decrypt(&sexp_plain_data, sexp_enc_data, ((DECRYPT_KEY *)key)->sexp_key))) { - fprintf(stderr, "Could not decrypt fek via s-exp, (error = 0x%x)\n", rc); + if ((rc = gcry_pk_decrypt(&sexp_plain_data, sexp_enc_data, + ((DECRYPT_KEY*)key)->sexp_key))) { + fprintf(stderr, "Could not decrypt fek via s-exp, (error = " + "0x%x)\n", rc); errno = -1; return FALSE; } - sexp_plain_data = gcry_sexp_find_token(sexp_plain_data, "value", 0); if (!mpi_buf) { - fprintf(stderr, "Could find value in s-exp, (error = 0x%x)\n", rc); + fprintf(stderr, "Could find value in s-exp, (error = 0x%x)\n", + rc); errno = -1; return FALSE; } - mpi_buf = gcry_sexp_nth_mpi(sexp_plain_data, 1, GCRYMPI_FMT_USG); - if ((rc = gcry_mpi_print(GCRYMPI_FMT_USG, data, data_size, &size, mpi_buf))) { - fprintf(stderr, "Could copy decrypted data back, (error = 0x%x)\n", rc); + if ((rc = gcry_mpi_print(GCRYMPI_FMT_USG, data, data_size, &size, + mpi_buf))) { + fprintf(stderr, "Could copy decrypted data back, (error = " + "0x%x)\n", rc); errno = -1; return FALSE; } - // remove the pkcs1 padding - for (padding_length = 1;(padding_lengthdata // todo: release all gcry_ac_data_destroy(in); - return size - padding_length; -#endif // USER_CRYPTOAPI_RSA (else) } unsigned int decrypt_decrypt_sector(decrypt_key *key, void *data, - unsigned long long offset) { + unsigned long long offset) +{ gcry_error_t err; - DECRYPT_KEY *dkey = (DECRYPT_KEY *)key; + DECRYPT_KEY *dkey = (DECRYPT_KEY*)key; - if ((err = gcry_cipher_reset(dkey->gcry_cipher_hd))) { + if ((err = gcry_cipher_reset(dkey->gcry_cipher_hd))) fprintf(stderr, "sector_decrypt: error is %u.\n", err); - } - // FIXME: Why are we not calling gcry_cipher_setiv() here instead of // doing it by hand after the decryption? // It wants iv length 8 but we give it 16 for AES256 so it does not // like it... - - if ((err = gcry_cipher_decrypt(dkey->gcry_cipher_hd, - data, 512, NULL, 0))) { + if ((err = gcry_cipher_decrypt(dkey->gcry_cipher_hd, data, 512, NULL, + 0))) fprintf(stderr, "sector_decrypt: error is %u.\n", err); - } - /* Apply the IV. */ if (dkey->alg_id == CALG_AES_256) { ((u64*)data)[0] ^= 0x5816657be9161312LL + offset; @@ -654,39 +603,41 @@ unsigned int decrypt_decrypt_sector(decrypt_key *key, void *data, return 512; } -decrypt_key *decrypt_make_key(decrypt_session *session __attribute__((unused)), - unsigned int data_size __attribute__((unused)), - unsigned char *data) { +decrypt_key *decrypt_make_key(decrypt_session *session __attribute__ ((unused)), + unsigned int data_size __attribute__ ((unused)), + unsigned char *data) +{ DECRYPT_KEY *key; unsigned int key_size, gcry_algo; gcry_error_t err; key_size = *(u32*)data; - if (!(key = (DECRYPT_KEY *)malloc(sizeof(DECRYPT_KEY)))) { + if (!(key = (DECRYPT_KEY*)malloc(sizeof(DECRYPT_KEY)))) { errno = -1; return NULL; } - key_size = *(u32*)data; key->alg_id = *(u32*)(data + 8); key->key_data = data + 16; switch (key->alg_id) { case CALG_DESX: - fprintf(stderr, "DESX key of %u bytes\n", key_size); + //fprintf(stderr, "DESX key of %u bytes\n", key_size); gcry_algo = desx_algorithm_id; break; case CALG_3DES: - fprintf(stderr, "3DES Key of %u bytes\n", key_size); - gcry_algo = GCRY_CIPHER_3DES; + //fprintf(stderr, "3DES Key of %u bytes\n", key_size); + gcry_algo = GCRY_CIPHER_3DES; break; case CALG_AES_256: - fprintf(stderr, "AES Key of %u bytes\n", key_size); + //fprintf(stderr, "AES Key of %u bytes\n", key_size); gcry_algo = GCRY_CIPHER_AES256; break; default: fprintf(stderr, "DES key of %u bytes\n", key_size); + fprintf(stderr, "This probably will not work... " + "It is completely untested.\n"); gcry_algo = GCRY_CIPHER_DES; break; } @@ -697,8 +648,7 @@ decrypt_key *decrypt_make_key(decrypt_session *session __attribute__((unused)), return 0; } if ((err = gcry_cipher_setkey(key->gcry_cipher_hd, key->key_data, - key_size))) { + key_size))) fprintf(stderr, "gcry_cipher_setkey failed with 0x%x.\n", err); - } - return (decrypt_key *)key; + return (decrypt_key*)key; } diff --git a/ntfsprogs/decrypt.h b/ntfsprogs/decrypt.h index 3d919ddc..c1cb8c80 100644 --- a/ntfsprogs/decrypt.h +++ b/ntfsprogs/decrypt.h @@ -27,16 +27,16 @@ typedef void *decrypt_session; typedef void *decrypt_key; extern decrypt_session *decrypt_open(void); -extern void decrypt_close(decrypt_session *session); -extern decrypt_key *decrypt_user_key_open(decrypt_session *session, - int thumb_size, void *thumb_print); -extern void decrypt_user_key_close(decrypt_key *key); -extern unsigned int decrypt_decrypt(decrypt_key *key, unsigned int data_size, - unsigned char *data); -extern unsigned int decrypt_decrypt_sector(decrypt_key *key, void *data, - unsigned long long offset); -extern decrypt_key *decrypt_make_key(decrypt_session *session, - unsigned int data_size, unsigned char *data); -extern int decrypt_get_block_size(decrypt_key *key); +extern void decrypt_close(decrypt_session * session); +extern decrypt_key *decrypt_user_key_open(decrypt_session * session, + int thumb_size, void *thumb_print); +extern void decrypt_user_key_close(decrypt_key * key); +extern unsigned int decrypt_decrypt(decrypt_key * key, unsigned int data_size, + unsigned char *data); +extern unsigned int decrypt_decrypt_sector(decrypt_key * key, void *data, + unsigned long long offset); +extern decrypt_key *decrypt_make_key(decrypt_session * session, + unsigned int data_size, unsigned char *data); +extern int decrypt_get_block_size(decrypt_key * key); #endif /* defined _NTFS_DECRYPT_H */ diff --git a/ntfsprogs/ntfsdecrypt.c b/ntfsprogs/ntfsdecrypt.c index 2212a166..a97497ba 100644 --- a/ntfsprogs/ntfsdecrypt.c +++ b/ntfsprogs/ntfsdecrypt.c @@ -1,9 +1,8 @@ /** * ntfsdecrypt - Part of the Linux-NTFS project. * - * Copyright (c) 2003 Richard Russon - * Copyright (c) 2003 Anton Altaparmakov * Copyright (c) 2005 Yuval Fledel + * Copyright (c) 2005 Anton Altaparmakov * * This utility will decrypt files and print on the standard output. * @@ -40,26 +39,27 @@ #include "decrypt.h" struct options { - char *device; /* Device/File to work with */ - char *file; /* File to display */ - s64 inode; /* Inode to work with */ - ATTR_TYPES attr; /* Attribute type to display */ - int force; /* Override common sense */ - int quiet; /* Less output */ - int verbose; /* Extra output */ + char *device; /* Device/File to work with */ + char *file; /* File to display */ + s64 inode; /* Inode to work with */ + ATTR_TYPES attr; /* Attribute type to display */ + int force; /* Override common sense */ + int quiet; /* Less output */ + int verbose; /* Extra output */ }; -static const char *EXEC_NAME = "ntfscat"; +static const char *EXEC_NAME = "ntfsdecrypt"; static struct options opts; -GEN_PRINTF (Eprintf, stderr, NULL, FALSE) -GEN_PRINTF (Vprintf, stderr, &opts.verbose, TRUE) -GEN_PRINTF (Qprintf, stderr, &opts.quiet, FALSE) -static GEN_PRINTF (Printf, stderr, NULL, FALSE) +GEN_PRINTF(Eprintf, stderr, NULL, FALSE) +GEN_PRINTF(Vprintf, stderr, &opts.verbose, TRUE) +GEN_PRINTF(Qprintf, stderr, &opts.quiet, FALSE) +static GEN_PRINTF(Printf, stderr, NULL, FALSE) static ntfschar EFS[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('E'), - const_cpu_to_le16('F'), const_cpu_to_le16('S'), - const_cpu_to_le16('\0') }; + const_cpu_to_le16('F'), const_cpu_to_le16('S'), + const_cpu_to_le16('\0') +}; static const int EFS_name_length = 4; /** @@ -69,12 +69,13 @@ static const int EFS_name_length = 4; * * Return: none */ -static void version (void) +static void version(void) { - Printf ("\n%s v%s - Concatenate files and print on the standard output.\n\n", - EXEC_NAME, VERSION); - Printf ("Copyright (c) 2003 Richard Russon\n"); - Printf ("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); + Printf("\n%s v%s - Decrypt and concatenate files and print on the " + "standard output.\n\n", EXEC_NAME, VERSION); + Printf("Copyright (c) 2005 Yuval Fledel\n"); + Printf("Copyright (c) 2005 Anton Altaparmakov\n"); + Printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); } /** @@ -84,21 +85,18 @@ static void version (void) * * Return: none */ -static void usage (void) +static void usage(void) { - Printf ("\nUsage: %s [options] device [file]\n\n" - " -a, --attribute num Display this attribute\n" - " -i, --inode num Display this inode\n\n" - " -f --force Use less caution\n" - " -h --help Print this help\n" - " -q --quiet Less output\n" - " -V --version Version information\n" - " -v --verbose More output\n\n", - //" -N --name Display this attribute name", - //" -F --file Display this file", - //" -r --raw Display the compressed or encrypted file", - EXEC_NAME); - Printf ("%s%s\n", ntfs_bugs, ntfs_home); + Printf("\nUsage: %s [options] device [file]\n\n" + " -i, --inode num Display this inode\n\n" + " -f --force Use less caution\n" + " -h --help Print this help\n" + " -q --quiet Less output\n" + " -V --version Version information\n" + " -v --verbose More output\n\n", + //" -r --raw Display the compressed or encrypted file", + EXEC_NAME); + Printf("%s%s\n", ntfs_bugs, ntfs_home); } /** @@ -110,37 +108,35 @@ static void usage (void) * Return: 1 Success * 0 Error, one or more problems */ -static int parse_options (int argc, char **argv) +static int parse_options(int argc, char **argv) { - static const char *sopt = "-a:fh?i:qVv"; // F:N: + static const char *sopt = "-fh?i:qVv"; // F:N: static const struct option lopt[] = { - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "inode", required_argument, NULL, 'i' }, - { "quiet", no_argument, NULL, 'q' }, - { "version", no_argument, NULL, 'V' }, - { "verbose", no_argument, NULL, 'v' }, - // { "file", required_argument, NULL, 'F' }, - // { "name", required_argument, NULL, 'N' }, - { NULL, 0, NULL, 0 } + {"force", no_argument, NULL, 'f'}, + {"help", no_argument, NULL, 'h'}, + {"inode", required_argument, NULL, 'i'}, + {"quiet", no_argument, NULL, 'q'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} }; char c = -1; - int err = 0; - int ver = 0; + int err = 0; + int ver = 0; int help = 0; - opterr = 0; /* We'll handle the errors, thank you. */ + opterr = 0; /* We'll handle the errors, thank you. */ opts.inode = -1; - while ((c = getopt_long (argc, argv, sopt, lopt, NULL)) != (char)-1) { + while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != (char)-1) { switch (c) { case 1: /* A non-option argument */ if (!opts.device) { - opts.device = argv[optind-1]; + opts.device = argv[optind - 1]; } else if (!opts.file) { - opts.file = argv[optind-1]; + opts.file = argv[optind - 1]; } else { Eprintf("You must specify exactly one file.\n"); err++; @@ -155,7 +151,8 @@ static int parse_options (int argc, char **argv) break; case 'i': if (opts.inode != -1) - Eprintf("You must specify exactly one inode.\n"); + Eprintf + ("You must specify exactly one inode.\n"); else if (utils_parse_size(optarg, &opts.inode, FALSE)) break; else @@ -172,7 +169,7 @@ static int parse_options (int argc, char **argv) opts.verbose++; break; default: - Eprintf ("Unknown option '%s'.\n", argv[optind-1]); + Eprintf("Unknown option '%s'.\n", argv[optind - 1]); err++; break; } @@ -182,22 +179,22 @@ static int parse_options (int argc, char **argv) opts.quiet = 0; } else { if (opts.device == NULL) { - Eprintf ("You must specify a device.\n"); + Eprintf("You must specify a device.\n"); err++; } else if (opts.file == NULL && opts.inode == -1) { - Eprintf ("You must specify a file or inode " - "with the -i option.\n"); + Eprintf("You must specify a file or inode " + "with the -i option.\n"); err++; } else if (opts.file != NULL && opts.inode != -1) { - Eprintf ("You can't specify both a file and inode.\n"); + Eprintf("You can't specify both a file and inode.\n"); err++; } if (opts.quiet && opts.verbose) { Eprintf("You may not use --quiet and --verbose at the " - "same time.\n"); + "same time.\n"); err++; } } @@ -213,22 +210,22 @@ static int parse_options (int argc, char **argv) /** * cat */ -static int cat_decrypt(ntfs_inode *inode, decrypt_key *fek) +static int cat_decrypt(ntfs_inode * inode, decrypt_key * fek) { - int bufsize = 512; + int bufsize = 512; char *buffer; ntfs_attr *attr; s64 bytes_read, written, offset, total; unsigned int i; - buffer = malloc (bufsize); + buffer = malloc(bufsize); if (!buffer) return 1; - attr = ntfs_attr_open (inode, AT_DATA, NULL, 0); + attr = ntfs_attr_open(inode, AT_DATA, NULL, 0); if (!attr) { - Eprintf ("Cannot cat a directory.\n"); - free (buffer); + Eprintf("Cannot cat a directory.\n"); + free(buffer); return 1; } @@ -241,43 +238,43 @@ static int cat_decrypt(ntfs_inode *inode, decrypt_key *fek) attr->data_size = attr->initialized_size = attr->allocated_size; offset = 0; - while (total>0) { - bytes_read = ntfs_attr_pread (attr, offset, 512, buffer); + while (total > 0) { + bytes_read = ntfs_attr_pread(attr, offset, 512, buffer); if (bytes_read == -1) { - perror ("ERROR: Couldn't read file"); + perror("ERROR: Couldn't read file"); break; } if (!bytes_read) break; - if ((i = decrypt_decrypt_sector(fek, buffer, offset)) - < bytes_read) { - perror ("ERROR: Couldn't decrypt all data!"); + if ((i = decrypt_decrypt_sector(fek, buffer, offset)) < + bytes_read) { + perror("ERROR: Couldn't decrypt all data!"); Eprintf("%u/%lld/%lld/%lld\n", i, (long long)bytes_read, - (long long)offset, (long long)total); + (long long)offset, (long long)total); break; } if (bytes_read > total) bytes_read = total; - written = fwrite (buffer, 1, bytes_read, stdout); + written = fwrite(buffer, 1, bytes_read, stdout); if (written != bytes_read) { - perror ("ERROR: Couldn't output all data!"); + perror("ERROR: Couldn't output all data!"); break; } offset += bytes_read; total -= bytes_read; } - ntfs_attr_close (attr); - free (buffer); + ntfs_attr_close(attr); + free(buffer); return 0; } /** * get_fek */ -static decrypt_key *get_fek (ntfs_inode *inode) +static decrypt_key *get_fek(ntfs_inode * inode) { ntfs_attr *na; char *efs_buffer, *ddf, *certificate, *hash_data, *fek_buf; @@ -287,8 +284,8 @@ static decrypt_key *get_fek (ntfs_inode *inode) decrypt_key *key; /* obtain the $EFS contents */ - na = ntfs_attr_open (inode, AT_LOGGED_UTILITY_STREAM, - EFS, EFS_name_length); + na = ntfs_attr_open(inode, AT_LOGGED_UTILITY_STREAM, + EFS, EFS_name_length); if (!na) { perror("Error"); return NULL; @@ -300,8 +297,8 @@ static decrypt_key *get_fek (ntfs_inode *inode) return NULL; } - if (ntfs_attr_pread(na, 0, na->data_size, efs_buffer) != - na->data_size) { + if (ntfs_attr_pread(na, 0, na->data_size, efs_buffer) != + na->data_size) { perror("ntfs_attr_pread failed"); free(efs_buffer); return NULL; @@ -309,37 +306,37 @@ static decrypt_key *get_fek (ntfs_inode *inode) ntfs_attr_close(na); /* init the CryptoAPI */ - if(!(session = decrypt_open())) { + if (!(session = decrypt_open())) { perror("Could not init the cryptoAPI."); return NULL; } /* iterate through the DDFs & DRFs until you obtain a key */ - ddf = efs_buffer + le32_to_cpu(*(u32 *)(efs_buffer+0x40)); + ddf = efs_buffer + le32_to_cpu(*(u32 *)(efs_buffer + 0x40)); ddf_count = le32_to_cpu(*(u32 *)ddf); ddf = ddf + 0x04; - for (i=0;i