Commit 8c54d938 authored by Milan Broz's avatar Milan Broz

Add crypt_last_error() API call (using crypt context).

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@623 36d66b0a-2a48-0410-832c-cd162a569da5
parent d7960b93
2011-10-05 Milan Broz <mbroz@redhat.com>
* Support Nettle 2.4 crypto backend (for ripemd160).
* If device is not rotational, do not use Gutmann wipe method.
* Add crypt_last_error() API call.
2011-09-22 Milan Broz <mbroz@redhat.com>
* Support key-slot option for luksOpen (use only explicit keyslot).
......
......@@ -22,6 +22,7 @@
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
#define DEFAULT_MEM_ALIGNMENT 4096
#define MAX_ERROR_LENGTH 512
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
......
......@@ -882,6 +882,18 @@ int crypt_header_restore(struct crypt_device *cd,
/**
* Receives last reported error
*
* @param cd crypt device handle
* @param buf buffef for message
* @param size size of buffer
*
* @note Note that this is old API function using global context.
* All error messages are reported also through log callback.
*/
void crypt_last_error(struct crypt_device *cd, char *buf, size_t size);
/**
* Receives last reported error, DEPRECATED
*
* @param buf buffef for message
* @param size size of buffer
*
......
......@@ -50,6 +50,7 @@ CRYPTSETUP_1.0 {
crypt_keyslot_max;
crypt_keyslot_status;
crypt_last_error;
crypt_get_error;
crypt_get_dir;
crypt_set_debug_level;
......
......@@ -71,11 +71,14 @@ struct crypt_device {
void *confirm_usrptr;
int (*password)(const char *msg, char *buf, size_t length, void *usrptr);
void *password_usrptr;
/* last error message */
char error[MAX_ERROR_LENGTH];
};
/* Global error */
/* FIXME: not thread safe, remove this later */
static char global_error[512] = {0};
static char global_error[MAX_ERROR_LENGTH] = {0};
/* Log helper */
static void (*_default_log)(int level, const char *msg, void *usrptr) = NULL;
......@@ -100,14 +103,21 @@ void crypt_log(struct crypt_device *cd, int level, const char *msg)
_default_log(level, msg, NULL);
}
/* Set global error, ugly hack... */
void set_global_error(const char *error)
static void crypt_set_error(struct crypt_device *cd, const char *error)
{
size_t size = strlen(error);
strncpy(global_error, error, sizeof(global_error) - 2);
if (size < sizeof(global_error) && global_error[size - 1] == '\n')
/* Set global error, ugly hack... */
strncpy(global_error, error, MAX_ERROR_LENGTH - 2);
if (size < MAX_ERROR_LENGTH && global_error[size - 1] == '\n')
global_error[size - 1] = '\0';
/* Set error string per context */
if (cd) {
strncpy(cd->error, error, MAX_ERROR_LENGTH - 2);
if (size < MAX_ERROR_LENGTH && cd->error[size - 1] == '\n')
cd->error[size - 1] = '\0';
}
}
__attribute__((format(printf, 5, 6)))
......@@ -131,7 +141,7 @@ void logger(struct crypt_device *cd, int level, const char *file,
#endif
if (level == CRYPT_LOG_ERROR)
set_global_error(target);
crypt_set_error(cd, target);
}
va_end(argp);
......@@ -429,19 +439,30 @@ void crypt_set_password_callback(struct crypt_device *cd,
cd->password_usrptr = usrptr;
}
/* Deprecated global error interface */
void crypt_get_error(char *buf, size_t size)
static void _get_error(char *error, char *buf, size_t size)
{
if (!buf || size < 1)
global_error[0] = '\0';
else if (*global_error) {
strncpy(buf, global_error, size - 1);
error[0] = '\0';
else if (*error) {
strncpy(buf, error, size - 1);
buf[size - 1] = '\0';
global_error[0] = '\0';
error[0] = '\0';
} else
buf[0] = '\0';
}
void crypt_last_error(struct crypt_device *cd, char *buf, size_t size)
{
if (cd)
return _get_error(cd->error, buf, size);
}
/* Deprecated global error interface */
void crypt_get_error(char *buf, size_t size)
{
return _get_error(global_error, buf, size);
}
const char *crypt_get_dir(void)
{
return dm_get_dir();
......
......@@ -441,24 +441,24 @@ static int _setup(void)
return 0;
}
void check_ok(int status, int line, const char *func)
void check_ok(struct crypt_device *cd, int status, int line, const char *func)
{
char buf[256];
if (status) {
crypt_get_error(buf, sizeof(buf));
crypt_last_error(cd, buf, sizeof(buf));
printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
_cleanup();
exit(-1);
}
}
void check_ko(int status, int line, const char *func)
void check_ko(struct crypt_device *cd, int status, int line, const char *func)
{
char buf[256];
memset(buf, 0, sizeof(buf));
crypt_get_error(buf, sizeof(buf));
crypt_last_error(cd, buf, sizeof(buf));
if (status >= 0) {
printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
_cleanup();
......@@ -483,11 +483,13 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch
printf(" [%s,%s:%d] %s\n", msg, func, line, tst);
}
}
/* crypt_device context must be "cd" to parse error properly here */
#define OK_(x) do { xlog("(success)", #x, __FUNCTION__, __LINE__, NULL); \
check_ok((x), __LINE__, __FUNCTION__); \
check_ok(cd, (x), __LINE__, __FUNCTION__); \
} while(0)
#define FAIL_(x, y) do { xlog("(fail) ", #x, __FUNCTION__, __LINE__, y); \
check_ko((x), __LINE__, __FUNCTION__); \
check_ko(cd, (x), __LINE__, __FUNCTION__); \
} while(0)
#define EQ_(x, y) do { xlog("(equal) ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
if ((x) != (y)) check_equal(__LINE__, __FUNCTION__); \
......@@ -495,11 +497,9 @@ void xlog(const char *msg, const char *tst, const char *func, int line, const ch
#define RUN_(x, y) do { printf("%s: %s\n", #x, (y)); x(); } while (0)
// NEW API tests
static void AddDevicePlain(void)
{
struct crypt_device *cd, *cd2;
struct crypt_device *cd;
struct crypt_params_plain params = {
.hash = "sha1",
.skip = 0,
......@@ -654,11 +654,12 @@ static void AddDevicePlain(void)
OK_(crypt_init(&cd,DEVICE_1));
OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
FAIL_(crypt_init_by_name_and_header(&cd2, CDEVICE_1, H_DEVICE),"can't init plain device by header device");
OK_(crypt_init_by_name(&cd2,CDEVICE_1));
OK_(crypt_deactivate(cd,CDEVICE_1));
crypt_free(cd);
crypt_free(cd2);
FAIL_(crypt_init_by_name_and_header(&cd, CDEVICE_1, H_DEVICE),"can't init plain device by header device");
OK_(crypt_init_by_name(&cd, CDEVICE_1));
OK_(crypt_deactivate(cd, CDEVICE_1));
crypt_free(cd);
OK_(crypt_init(&cd,DEVICE_1));
OK_(crypt_format(cd,CRYPT_PLAIN,cipher,cipher_mode,NULL,NULL,key_size,&params));
......@@ -812,6 +813,7 @@ static void CallbacksTest(void)
char *cipher = "aes";
char *cipher_mode = "cbc-essiv:sha256";
char *passphrase = PASSPHRASE;
char buf1[256] = {0}, buf2[256] = {0};
OK_(crypt_init(&cd, DEVICE_1));
crypt_set_log_callback(cd, &new_log, NULL);
......@@ -833,6 +835,22 @@ static void CallbacksTest(void)
EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
OK_(crypt_deactivate(cd, CDEVICE_1));
// Check error reporting.
// This must fail and create error message
crypt_deactivate(cd, CDEVICE_1);
// Here context must be the same
crypt_get_error(buf1, sizeof(buf1));
crypt_last_error(cd, buf2, sizeof(buf2));
OK_(!*buf1);
OK_(!*buf2);
OK_(strcmp(buf1, buf2));
crypt_get_error(buf1, sizeof(buf1));
crypt_last_error(cd, buf2, sizeof(buf2));
OK_(*buf1);
OK_(*buf2);
crypt_free(cd);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment