Support basic asymmetric operations: encrypt, decrypt, sign and verify. Co-developed-by: lei he <helei.sig11@xxxxxxxxxxxxx> Signed-off-by: lei he <helei.sig11@xxxxxxxxxxxxx> Signed-off-by: zhenwei pi <pizhenwei@xxxxxxxxxxxxx> --- crypto/akcipher.c | 78 +++++++++++++++++++++ crypto/meson.build | 1 + include/crypto/akcipher.h | 139 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 crypto/akcipher.c create mode 100644 include/crypto/akcipher.h diff --git a/crypto/akcipher.c b/crypto/akcipher.c new file mode 100644 index 0000000000..1e52f2fd76 --- /dev/null +++ b/crypto/akcipher.c @@ -0,0 +1,78 @@ +/* + * QEMU Crypto akcipher algorithms + * + * Copyright (c) 2022 Bytedance + * Author: zhenwei pi <pizhenwei@xxxxxxxxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "qemu/osdep.h" +#include "qemu/host-utils.h" +#include "qapi/error.h" +#include "crypto/akcipher.h" + +QCryptoAkcipher *qcrypto_akcipher_new(QCryptoAkcipherAlgorithm alg, + QCryptoAkcipherKeyType type, + const uint8_t *key, size_t keylen, + void *para, Error **errp) +{ + QCryptoAkcipher *akcipher = NULL; + + return akcipher; +} + +int qcrypto_akcipher_encrypt(QCryptoAkcipher *akcipher, + const void *data, size_t data_len, + void *enc, size_t enc_len, Error **errp) +{ + const QCryptoAkcipherDriver *drv = akcipher->driver; + + return drv->encrypt(akcipher, data, data_len, enc, enc_len, errp); +} + +int qcrypto_akcipher_decrypt(struct QCryptoAkcipher *akcipher, + const void *enc, size_t enc_len, + void *data, size_t data_len, Error **errp) +{ + const QCryptoAkcipherDriver *drv = akcipher->driver; + + return drv->decrypt(akcipher, enc, enc_len, data, data_len, errp); +} + +int qcrypto_akcipher_sign(struct QCryptoAkcipher *akcipher, + const void *data, size_t data_len, + void *sig, size_t sig_len, Error **errp) +{ + const QCryptoAkcipherDriver *drv = akcipher->driver; + + return drv->sign(akcipher, data, data_len, sig, sig_len, errp); +} + +int qcrypto_akcipher_verify(struct QCryptoAkcipher *akcipher, + const void *sig, size_t sig_len, + const void *data, size_t data_len, Error **errp) +{ + const QCryptoAkcipherDriver *drv = akcipher->driver; + + return drv->verify(akcipher, sig, sig_len, data, data_len, errp); +} + +int qcrypto_akcipher_free(struct QCryptoAkcipher *akcipher, Error **errp) +{ + const QCryptoAkcipherDriver *drv = akcipher->driver; + + return drv->free(akcipher, errp); +} diff --git a/crypto/meson.build b/crypto/meson.build index 19c44bea89..c32b57aeda 100644 --- a/crypto/meson.build +++ b/crypto/meson.build @@ -19,6 +19,7 @@ crypto_ss.add(files( 'tlscredspsk.c', 'tlscredsx509.c', 'tlssession.c', + 'akcipher.c', )) if nettle.found() diff --git a/include/crypto/akcipher.h b/include/crypto/akcipher.h new file mode 100644 index 0000000000..03cc3bf46b --- /dev/null +++ b/include/crypto/akcipher.h @@ -0,0 +1,139 @@ +/* + * QEMU Crypto asymmetric algorithms + * + * Copyright (c) 2022 Bytedance + * Author: zhenwei pi <pizhenwei@xxxxxxxxxxxxx> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef QCRYPTO_AKCIPHER_H +#define QCRYPTO_AKCIPHER_H + +#include "qemu/typedefs.h" +#include "qapi/qapi-types-crypto.h" + +typedef struct QCryptoAkcipher QCryptoAkcipher; +typedef struct QCryptoAkcipherDriver QCryptoAkcipherDriver; + +struct QCryptoAkcipherDriver { + int (*encrypt)(struct QCryptoAkcipher *akcipher, + const void *data, size_t data_len, + void *enc, size_t enc_len, Error **errp); + int (*decrypt)(struct QCryptoAkcipher *akcipher, + const void *enc, size_t enc_len, + void *data, size_t data_len, Error **errp); + int (*sign)(struct QCryptoAkcipher *akcipher, + const void *data, size_t data_len, + void *sig, size_t sig_len, Error **errp); + int (*verify)(struct QCryptoAkcipher *akcipher, + const void *sig, size_t sig_len, + const void *data, size_t data_len, Error **errp); + int (*free)(struct QCryptoAkcipher *akcipher, Error **errp); +}; + +struct QCryptoAkcipher { + QCryptoAkcipherAlgorithm alg; + QCryptoAkcipherKeyType type; + uint8_t *key; + size_t keylen; + int max_plaintext_len; + int max_ciphertext_len; + int max_signature_len; + int max_dgst_len; + QCryptoAkcipherDriver *driver; +}; + +QCryptoAkcipher *qcrypto_akcipher_new(QCryptoAkcipherAlgorithm alg, + QCryptoAkcipherKeyType type, + const uint8_t *key, size_t keylen, + void *para, Error **errp); + +/** + * qcrypto_akcipher_encrypt: + * @akcipher: akcipher used to do encryption + * @data: plaintext pending to be encrypted + * @data_len: length of the plaintext, MUST less or equal + * akcipher->max_plaintext_len + * @enc: buffer to store the ciphertext + * @enc_len: the length of ciphertext buffer, usually equals to + * akcipher->max_ciphertext_len + * @errp: error pointer + * + * Encrypt data and write ciphertext into enc + * + * Returns: length of ciphertext if encrypt succeed, otherwise -1 is returned + */ +int qcrypto_akcipher_encrypt(QCryptoAkcipher *akcipher, + const void *data, size_t data_len, + void *enc, size_t enc_len, Error **errp); + +/** + * qcrypto_akcipher_decrypt: + * @akcipher: akcipher used to do decryption + * @enc: ciphertext to be decrypted + * @enc_len: the length of ciphertext + * @data: buffer to store the plaintext + * @data_len: length of the plaintext buffer, usually equals to + * akcipher->max_plaintext_len + * @errp: error pointer + * + * Decrypt ciphertext and write plaintext into data + * + * Returns: length of plaintext if decrypt succeed, otherwise -1 is returned + */ +int qcrypto_akcipher_decrypt(struct QCryptoAkcipher *akcipher, + const void *enc, size_t enc_len, + void *data, size_t data_len, Error **errp); + +/** + * qcrypto_akcipher_sign: + * @akcipher: akcipher used to generate signature + * @data: data to be signed + * @data_len: the length of data + * @sig: buffer to store the signature + * @sig_len: length of the signature buffer, usually equals to + * akcipher->max_signature_len + * @errp: error pointer + * + * Generate signature for data using akcipher + * + * Returns: length of signature if succeed, otherwise -1 is returned + */ +int qcrypto_akcipher_sign(struct QCryptoAkcipher *akcipher, + const void *data, size_t data_len, + void *sig, size_t sig_len, Error **errp); + +/** + * qcrypto_akcipher_verify: + * @akcipher: akcipher used to do verifycation + * @sig: pointer to the signature + * @sig_len: length of the signature + * @data: pointer to original data + * @data_len: the length of data + * @errp: error pointer + * + * Verify the signature and the data match or not + * + * Returns: 0 for succeed, otherwise -1 is returned + */ +int qcrypto_akcipher_verify(struct QCryptoAkcipher *akcipher, + const void *sig, size_t sig_len, + const void *data, size_t data_len, Error **errp); + +int qcrypto_akcipher_free(struct QCryptoAkcipher *akcipher, Error **errp); + + +#endif /* QCRYPTO_AKCIPHER_H */ -- 2.25.1