From 9a9ddc7d22e14e14c9a6e97860cffada406adac3 Mon Sep 17 00:00:00 2001 From: Ondrej Kozina Date: Tue, 11 Oct 2022 10:50:17 +0200 Subject: [PATCH 2/5] Move cipher_dm2c to crypto utilities. (Gets renamed to crypt_capi_to_cipher) --- lib/libdevmapper.c | 84 +++------------------------------------------- lib/utils_crypt.c | 72 +++++++++++++++++++++++++++++++++++++++ lib/utils_crypt.h | 11 ++++-- 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 0e45a789..7fcf843f 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -476,27 +476,22 @@ static size_t int_log10(uint64_t x) return r; } -#define CLEN 64 /* 2*MAX_CIPHER_LEN */ -#define CLENS "63" /* for sscanf length + '\0' */ -#define CAPIL 144 /* should be enough to fit whole capi string */ -#define CAPIS "143" /* for sscanf of crypto API string + 16 + \0 */ - static int cipher_dm2c(const char *org_c, const char *org_i, unsigned tag_size, char *c_dm, int c_dm_size, char *i_dm, int i_dm_size) { int c_size = 0, i_size = 0, i; - char cipher[CLEN], mode[CLEN], iv[CLEN+1], tmp[CLEN]; - char capi[CAPIL]; + char cipher[MAX_CAPI_ONE_LEN], mode[MAX_CAPI_ONE_LEN], iv[MAX_CAPI_ONE_LEN+1], + tmp[MAX_CAPI_ONE_LEN], capi[MAX_CAPI_LEN]; if (!c_dm || !c_dm_size || !i_dm || !i_dm_size) return -EINVAL; - i = sscanf(org_c, "%" CLENS "[^-]-%" CLENS "s", cipher, tmp); + i = sscanf(org_c, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", cipher, tmp); if (i != 2) return -EINVAL; - i = sscanf(tmp, "%" CLENS "[^-]-%" CLENS "s", mode, iv); + i = sscanf(tmp, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", mode, iv); if (i == 1) { memset(iv, 0, sizeof(iv)); strncpy(iv, mode, sizeof(iv)-1); @@ -543,75 +538,6 @@ static int cipher_dm2c(const char *org_c, const char *org_i, unsigned tag_size, return 0; } -static int cipher_c2dm(char **org_c, char **org_i, const char *c_dm, const char *i_dm) -{ - char cipher[CLEN], mode[CLEN], iv[CLEN], auth[CLEN]; - char tmp[CAPIL], dmcrypt_tmp[CAPIL*2], capi[CAPIL+1]; - size_t len; - int i; - - if (!c_dm) - return -EINVAL; - - /* legacy mode */ - if (strncmp(c_dm, "capi:", 4)) { - if (!(*org_c = strdup(c_dm))) - return -ENOMEM; - *org_i = NULL; - return 0; - } - - /* modes with capi: prefix */ - i = sscanf(c_dm, "capi:%" CAPIS "[^-]-%" CLENS "s", tmp, iv); - if (i != 2) - return -EINVAL; - - len = strlen(tmp); - if (len < 2) - return -EINVAL; - - if (tmp[len-1] == ')') - tmp[len-1] = '\0'; - - if (sscanf(tmp, "rfc4309(%" CAPIS "s", capi) == 1) { - if (!(*org_i = strdup("aead"))) - return -ENOMEM; - } else if (sscanf(tmp, "rfc7539(%" CAPIS "[^,],%" CLENS "s", capi, auth) == 2) { - if (!(*org_i = strdup(auth))) - return -ENOMEM; - } else if (sscanf(tmp, "authenc(%" CLENS "[^,],%" CAPIS "s", auth, capi) == 2) { - if (!(*org_i = strdup(auth))) - return -ENOMEM; - } else { - if (i_dm) { - if (!(*org_i = strdup(i_dm))) - return -ENOMEM; - } else - *org_i = NULL; - memset(capi, 0, sizeof(capi)); - strncpy(capi, tmp, sizeof(capi)-1); - } - - i = sscanf(capi, "%" CLENS "[^(](%" CLENS "[^)])", mode, cipher); - if (i == 2) - i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv); - else - i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv); - if (i < 0 || (size_t)i >= sizeof(dmcrypt_tmp)) { - free(*org_i); - *org_i = NULL; - return -EINVAL; - } - - if (!(*org_c = strdup(dmcrypt_tmp))) { - free(*org_i); - *org_i = NULL; - return -ENOMEM; - } - - return 0; -} - static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u) { size_t r = snprintf(buf, buf_size, " %s:%u", s, u); @@ -2066,7 +1992,7 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags, /* cipher */ if (get_flags & DM_ACTIVE_CRYPT_CIPHER) { - r = cipher_c2dm(CONST_CAST(char**)&cipher, + r = crypt_capi_to_cipher(CONST_CAST(char**)&cipher, CONST_CAST(char**)&integrity, rcipher, rintegrity); if (r < 0) diff --git a/lib/utils_crypt.c b/lib/utils_crypt.c index 83d0a2c5..4f4dbba8 100644 --- a/lib/utils_crypt.c +++ b/lib/utils_crypt.c @@ -31,6 +31,8 @@ #include "libcryptsetup.h" #include "utils_crypt.h" +#define MAX_CAPI_LEN_STR "143" /* for sscanf of crypto API string + 16 + \0 */ + int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, char *cipher_mode) { @@ -266,3 +268,73 @@ bool crypt_is_cipher_null(const char *cipher_spec) return false; return (strstr(cipher_spec, "cipher_null") || !strcmp(cipher_spec, "null")); } + +int crypt_capi_to_cipher(char **org_c, char **org_i, const char *c_dm, const char *i_dm) +{ + char cipher[MAX_CAPI_ONE_LEN], mode[MAX_CAPI_ONE_LEN], iv[MAX_CAPI_ONE_LEN], + auth[MAX_CAPI_ONE_LEN], tmp[MAX_CAPI_LEN], dmcrypt_tmp[MAX_CAPI_LEN*2], + capi[MAX_CAPI_LEN+1]; + size_t len; + int i; + + if (!c_dm) + return -EINVAL; + + /* legacy mode */ + if (strncmp(c_dm, "capi:", 4)) { + if (!(*org_c = strdup(c_dm))) + return -ENOMEM; + *org_i = NULL; + return 0; + } + + /* modes with capi: prefix */ + i = sscanf(c_dm, "capi:%" MAX_CAPI_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", tmp, iv); + if (i != 2) + return -EINVAL; + + len = strlen(tmp); + if (len < 2) + return -EINVAL; + + if (tmp[len-1] == ')') + tmp[len-1] = '\0'; + + if (sscanf(tmp, "rfc4309(%" MAX_CAPI_LEN_STR "s", capi) == 1) { + if (!(*org_i = strdup("aead"))) + return -ENOMEM; + } else if (sscanf(tmp, "rfc7539(%" MAX_CAPI_LEN_STR "[^,],%" MAX_CAPI_ONE_LEN_STR "s", capi, auth) == 2) { + if (!(*org_i = strdup(auth))) + return -ENOMEM; + } else if (sscanf(tmp, "authenc(%" MAX_CAPI_ONE_LEN_STR "[^,],%" MAX_CAPI_LEN_STR "s", auth, capi) == 2) { + if (!(*org_i = strdup(auth))) + return -ENOMEM; + } else { + if (i_dm) { + if (!(*org_i = strdup(i_dm))) + return -ENOMEM; + } else + *org_i = NULL; + memset(capi, 0, sizeof(capi)); + strncpy(capi, tmp, sizeof(capi)-1); + } + + i = sscanf(capi, "%" MAX_CAPI_ONE_LEN_STR "[^(](%" MAX_CAPI_ONE_LEN_STR "[^)])", mode, cipher); + if (i == 2) + i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s-%s", cipher, mode, iv); + else + i = snprintf(dmcrypt_tmp, sizeof(dmcrypt_tmp), "%s-%s", capi, iv); + if (i < 0 || (size_t)i >= sizeof(dmcrypt_tmp)) { + free(*org_i); + *org_i = NULL; + return -EINVAL; + } + + if (!(*org_c = strdup(dmcrypt_tmp))) { + free(*org_i); + *org_i = NULL; + return -ENOMEM; + } + + return 0; +} diff --git a/lib/utils_crypt.h b/lib/utils_crypt.h index 5922350a..a4a9b6ca 100644 --- a/lib/utils_crypt.h +++ b/lib/utils_crypt.h @@ -27,9 +27,12 @@ #include #include -#define MAX_CIPHER_LEN 32 -#define MAX_CIPHER_LEN_STR "31" -#define MAX_KEYFILES 32 +#define MAX_CIPHER_LEN 32 +#define MAX_CIPHER_LEN_STR "31" +#define MAX_KEYFILES 32 +#define MAX_CAPI_ONE_LEN 2 * MAX_CIPHER_LEN +#define MAX_CAPI_ONE_LEN_STR "63" /* for sscanf length + '\0' */ +#define MAX_CAPI_LEN 144 /* should be enough to fit whole capi string */ int crypt_parse_name_and_mode(const char *s, char *cipher, int *key_nums, char *cipher_mode); @@ -46,4 +49,6 @@ void crypt_log_hex(struct crypt_device *cd, bool crypt_is_cipher_null(const char *cipher_spec); +int crypt_capi_to_cipher(char **org_c, char **org_i, const char *c_dm, const char *i_dm); + #endif /* _UTILS_CRYPT_H */ -- 2.38.1