-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crypto: cipher: add afalg-backend cipher support
Adds afalg-backend cipher support: introduces some private APIs firstly, and then intergrates them into qcrypto_cipher_afalg_driver. Signed-off-by: Longpeng(Mike) <[email protected]> Signed-off-by: Daniel P. Berrange <[email protected]>
- Loading branch information
Showing
5 changed files
with
271 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
/* | ||
* QEMU Crypto af_alg-backend cipher support | ||
* | ||
* Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD. | ||
* | ||
* Authors: | ||
* Longpeng(Mike) <[email protected]> | ||
* | ||
* This work is licensed under the terms of the GNU GPL, version 2 or | ||
* (at your option) any later version. See the COPYING file in the | ||
* top-level directory. | ||
*/ | ||
#include "qemu/osdep.h" | ||
#include "qemu/sockets.h" | ||
#include "qemu-common.h" | ||
#include "qapi/error.h" | ||
#include "crypto/cipher.h" | ||
#include "cipherpriv.h" | ||
|
||
|
||
static char * | ||
qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg, | ||
QCryptoCipherMode mode, | ||
Error **errp) | ||
{ | ||
char *name; | ||
const char *alg_name; | ||
const char *mode_name; | ||
|
||
switch (alg) { | ||
case QCRYPTO_CIPHER_ALG_AES_128: | ||
case QCRYPTO_CIPHER_ALG_AES_192: | ||
case QCRYPTO_CIPHER_ALG_AES_256: | ||
alg_name = "aes"; | ||
break; | ||
case QCRYPTO_CIPHER_ALG_CAST5_128: | ||
alg_name = "cast5"; | ||
break; | ||
case QCRYPTO_CIPHER_ALG_SERPENT_128: | ||
case QCRYPTO_CIPHER_ALG_SERPENT_192: | ||
case QCRYPTO_CIPHER_ALG_SERPENT_256: | ||
alg_name = "serpent"; | ||
break; | ||
case QCRYPTO_CIPHER_ALG_TWOFISH_128: | ||
case QCRYPTO_CIPHER_ALG_TWOFISH_192: | ||
case QCRYPTO_CIPHER_ALG_TWOFISH_256: | ||
alg_name = "twofish"; | ||
break; | ||
|
||
default: | ||
error_setg(errp, "Unsupported cipher algorithm %d", alg); | ||
return NULL; | ||
} | ||
|
||
mode_name = QCryptoCipherMode_lookup[mode]; | ||
name = g_strdup_printf("%s(%s)", mode_name, alg_name); | ||
|
||
return name; | ||
} | ||
|
||
QCryptoAFAlg * | ||
qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, | ||
QCryptoCipherMode mode, | ||
const uint8_t *key, | ||
size_t nkey, Error **errp) | ||
{ | ||
QCryptoAFAlg *afalg; | ||
size_t expect_niv; | ||
char *name; | ||
|
||
name = qcrypto_afalg_cipher_format_name(alg, mode, errp); | ||
if (!name) { | ||
return NULL; | ||
} | ||
|
||
afalg = qcrypto_afalg_comm_alloc(AFALG_TYPE_CIPHER, name, errp); | ||
if (!afalg) { | ||
g_free(name); | ||
return NULL; | ||
} | ||
|
||
g_free(name); | ||
|
||
/* setkey */ | ||
if (qemu_setsockopt(afalg->tfmfd, SOL_ALG, ALG_SET_KEY, key, | ||
nkey) != 0) { | ||
error_setg_errno(errp, errno, "Set key failed"); | ||
qcrypto_afalg_comm_free(afalg); | ||
return NULL; | ||
} | ||
|
||
/* prepare msg header */ | ||
afalg->msg = g_new0(struct msghdr, 1); | ||
afalg->msg->msg_controllen += CMSG_SPACE(ALG_OPTYPE_LEN); | ||
expect_niv = qcrypto_cipher_get_iv_len(alg, mode); | ||
if (expect_niv) { | ||
afalg->msg->msg_controllen += CMSG_SPACE(ALG_MSGIV_LEN(expect_niv)); | ||
} | ||
afalg->msg->msg_control = g_new0(uint8_t, afalg->msg->msg_controllen); | ||
|
||
/* We use 1st msghdr for crypto-info and 2nd msghdr for IV-info */ | ||
afalg->cmsg = CMSG_FIRSTHDR(afalg->msg); | ||
afalg->cmsg->cmsg_type = ALG_SET_OP; | ||
afalg->cmsg->cmsg_len = CMSG_SPACE(ALG_OPTYPE_LEN); | ||
if (expect_niv) { | ||
afalg->cmsg = CMSG_NXTHDR(afalg->msg, afalg->cmsg); | ||
afalg->cmsg->cmsg_type = ALG_SET_IV; | ||
afalg->cmsg->cmsg_len = CMSG_SPACE(ALG_MSGIV_LEN(expect_niv)); | ||
} | ||
afalg->cmsg = CMSG_FIRSTHDR(afalg->msg); | ||
|
||
return afalg; | ||
} | ||
|
||
static int | ||
qcrypto_afalg_cipher_setiv(QCryptoCipher *cipher, | ||
const uint8_t *iv, | ||
size_t niv, Error **errp) | ||
{ | ||
struct af_alg_iv *alg_iv; | ||
size_t expect_niv; | ||
QCryptoAFAlg *afalg = cipher->opaque; | ||
|
||
expect_niv = qcrypto_cipher_get_iv_len(cipher->alg, cipher->mode); | ||
if (niv != expect_niv) { | ||
error_setg(errp, "Set IV len(%zu) not match expected(%zu)", | ||
niv, expect_niv); | ||
return -1; | ||
} | ||
|
||
/* move ->cmsg to next msghdr, for IV-info */ | ||
afalg->cmsg = CMSG_NXTHDR(afalg->msg, afalg->cmsg); | ||
|
||
/* build setiv msg */ | ||
afalg->cmsg->cmsg_level = SOL_ALG; | ||
alg_iv = (struct af_alg_iv *)CMSG_DATA(afalg->cmsg); | ||
alg_iv->ivlen = niv; | ||
memcpy(alg_iv->iv, iv, niv); | ||
|
||
return 0; | ||
} | ||
|
||
static int | ||
qcrypto_afalg_cipher_op(QCryptoAFAlg *afalg, | ||
const void *in, void *out, | ||
size_t len, bool do_encrypt, | ||
Error **errp) | ||
{ | ||
uint32_t *type = NULL; | ||
struct iovec iov; | ||
size_t ret, rlen, done = 0; | ||
uint32_t origin_controllen; | ||
|
||
origin_controllen = afalg->msg->msg_controllen; | ||
/* movev ->cmsg to first header, for crypto-info */ | ||
afalg->cmsg = CMSG_FIRSTHDR(afalg->msg); | ||
|
||
/* build encrypt msg */ | ||
afalg->cmsg->cmsg_level = SOL_ALG; | ||
afalg->msg->msg_iov = &iov; | ||
afalg->msg->msg_iovlen = 1; | ||
type = (uint32_t *)CMSG_DATA(afalg->cmsg); | ||
if (do_encrypt) { | ||
*type = ALG_OP_ENCRYPT; | ||
} else { | ||
*type = ALG_OP_DECRYPT; | ||
} | ||
|
||
do { | ||
iov.iov_base = (void *)in + done; | ||
iov.iov_len = len - done; | ||
|
||
/* send info to AF_ALG core */ | ||
ret = sendmsg(afalg->opfd, afalg->msg, 0); | ||
if (ret == -1) { | ||
error_setg_errno(errp, errno, "Send data to AF_ALG core failed"); | ||
return -1; | ||
} | ||
|
||
/* encrypto && get result */ | ||
rlen = read(afalg->opfd, out, ret); | ||
if (rlen == -1) { | ||
error_setg_errno(errp, errno, "Get result from AF_ALG core failed"); | ||
return -1; | ||
} | ||
assert(rlen == ret); | ||
|
||
/* do not update IV for following chunks */ | ||
afalg->msg->msg_controllen = 0; | ||
done += ret; | ||
} while (done < len); | ||
|
||
afalg->msg->msg_controllen = origin_controllen; | ||
|
||
return 0; | ||
} | ||
|
||
static int | ||
qcrypto_afalg_cipher_encrypt(QCryptoCipher *cipher, | ||
const void *in, void *out, | ||
size_t len, Error **errp) | ||
{ | ||
return qcrypto_afalg_cipher_op(cipher->opaque, in, out, | ||
len, true, errp); | ||
} | ||
|
||
static int | ||
qcrypto_afalg_cipher_decrypt(QCryptoCipher *cipher, | ||
const void *in, void *out, | ||
size_t len, Error **errp) | ||
{ | ||
return qcrypto_afalg_cipher_op(cipher->opaque, in, out, | ||
len, false, errp); | ||
} | ||
|
||
static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher) | ||
{ | ||
qcrypto_afalg_comm_free(cipher->opaque); | ||
} | ||
|
||
struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { | ||
.cipher_encrypt = qcrypto_afalg_cipher_encrypt, | ||
.cipher_decrypt = qcrypto_afalg_cipher_decrypt, | ||
.cipher_setiv = qcrypto_afalg_cipher_setiv, | ||
.cipher_free = qcrypto_afalg_comm_ctx_free, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters