1f0d92b56SLongpeng(Mike) /*
2f0d92b56SLongpeng(Mike) * QEMU Crypto af_alg support
3f0d92b56SLongpeng(Mike) *
4f0d92b56SLongpeng(Mike) * Copyright (c) 2017 HUAWEI TECHNOLOGIES CO., LTD.
5f0d92b56SLongpeng(Mike) *
6f0d92b56SLongpeng(Mike) * Authors:
7f0d92b56SLongpeng(Mike) * Longpeng(Mike) <longpeng2@huawei.com>
8f0d92b56SLongpeng(Mike) *
9f0d92b56SLongpeng(Mike) * This work is licensed under the terms of the GNU GPL, version 2 or
10f0d92b56SLongpeng(Mike) * (at your option) any later version. See the COPYING file in the
11f0d92b56SLongpeng(Mike) * top-level directory.
12f0d92b56SLongpeng(Mike) */
13f0d92b56SLongpeng(Mike) #include "qemu/osdep.h"
14f0d92b56SLongpeng(Mike) #include "qemu/cutils.h"
15f0d92b56SLongpeng(Mike) #include "qemu/sockets.h"
16f0d92b56SLongpeng(Mike) #include "qapi/error.h"
17f0d92b56SLongpeng(Mike) #include "afalgpriv.h"
18f0d92b56SLongpeng(Mike)
19f0d92b56SLongpeng(Mike) static bool
qcrypto_afalg_build_saddr(const char * type,const char * name,struct sockaddr_alg * salg,Error ** errp)20f0d92b56SLongpeng(Mike) qcrypto_afalg_build_saddr(const char *type, const char *name,
21f0d92b56SLongpeng(Mike) struct sockaddr_alg *salg, Error **errp)
22f0d92b56SLongpeng(Mike) {
23f0d92b56SLongpeng(Mike) salg->salg_family = AF_ALG;
24f0d92b56SLongpeng(Mike)
25f0d92b56SLongpeng(Mike) if (strnlen(type, SALG_TYPE_LEN_MAX) >= SALG_TYPE_LEN_MAX) {
26f0d92b56SLongpeng(Mike) error_setg(errp, "Afalg type(%s) is larger than %d bytes",
27f0d92b56SLongpeng(Mike) type, SALG_TYPE_LEN_MAX);
28f0d92b56SLongpeng(Mike) return false;
29f0d92b56SLongpeng(Mike) }
30f0d92b56SLongpeng(Mike)
31f0d92b56SLongpeng(Mike) if (strnlen(name, SALG_NAME_LEN_MAX) >= SALG_NAME_LEN_MAX) {
32f0d92b56SLongpeng(Mike) error_setg(errp, "Afalg name(%s) is larger than %d bytes",
33f0d92b56SLongpeng(Mike) name, SALG_NAME_LEN_MAX);
34f0d92b56SLongpeng(Mike) return false;
35f0d92b56SLongpeng(Mike) }
36f0d92b56SLongpeng(Mike)
37f0d92b56SLongpeng(Mike) pstrcpy((char *)salg->salg_type, SALG_TYPE_LEN_MAX, type);
38f0d92b56SLongpeng(Mike) pstrcpy((char *)salg->salg_name, SALG_NAME_LEN_MAX, name);
39f0d92b56SLongpeng(Mike)
40f0d92b56SLongpeng(Mike) return true;
41f0d92b56SLongpeng(Mike) }
42f0d92b56SLongpeng(Mike)
43f0d92b56SLongpeng(Mike) static int
qcrypto_afalg_socket_bind(const char * type,const char * name,Error ** errp)44f0d92b56SLongpeng(Mike) qcrypto_afalg_socket_bind(const char *type, const char *name,
45f0d92b56SLongpeng(Mike) Error **errp)
46f0d92b56SLongpeng(Mike) {
47f0d92b56SLongpeng(Mike) int sbind;
48f0d92b56SLongpeng(Mike) struct sockaddr_alg salg = {0};
49f0d92b56SLongpeng(Mike)
50f0d92b56SLongpeng(Mike) if (!qcrypto_afalg_build_saddr(type, name, &salg, errp)) {
51f0d92b56SLongpeng(Mike) return -1;
52f0d92b56SLongpeng(Mike) }
53f0d92b56SLongpeng(Mike)
54f0d92b56SLongpeng(Mike) sbind = qemu_socket(AF_ALG, SOCK_SEQPACKET, 0);
55f0d92b56SLongpeng(Mike) if (sbind < 0) {
56f0d92b56SLongpeng(Mike) error_setg_errno(errp, errno, "Failed to create socket");
57f0d92b56SLongpeng(Mike) return -1;
58f0d92b56SLongpeng(Mike) }
59f0d92b56SLongpeng(Mike)
60f0d92b56SLongpeng(Mike) if (bind(sbind, (const struct sockaddr *)&salg, sizeof(salg)) != 0) {
61f0d92b56SLongpeng(Mike) error_setg_errno(errp, errno, "Failed to bind socket");
6225657fc6SMarc-André Lureau close(sbind);
63f0d92b56SLongpeng(Mike) return -1;
64f0d92b56SLongpeng(Mike) }
65f0d92b56SLongpeng(Mike)
66f0d92b56SLongpeng(Mike) return sbind;
67f0d92b56SLongpeng(Mike) }
68f0d92b56SLongpeng(Mike)
69*8f525028SMarkus Armbruster QCryptoAFAlgo *
qcrypto_afalg_comm_alloc(const char * type,const char * name,Error ** errp)70f0d92b56SLongpeng(Mike) qcrypto_afalg_comm_alloc(const char *type, const char *name,
71f0d92b56SLongpeng(Mike) Error **errp)
72f0d92b56SLongpeng(Mike) {
73*8f525028SMarkus Armbruster QCryptoAFAlgo *afalg;
74f0d92b56SLongpeng(Mike)
75*8f525028SMarkus Armbruster afalg = g_new0(QCryptoAFAlgo, 1);
760a19d879SMichael Tokarev /* initialize crypto API socket */
77f0d92b56SLongpeng(Mike) afalg->opfd = -1;
78f0d92b56SLongpeng(Mike) afalg->tfmfd = qcrypto_afalg_socket_bind(type, name, errp);
79f0d92b56SLongpeng(Mike) if (afalg->tfmfd == -1) {
80f0d92b56SLongpeng(Mike) goto error;
81f0d92b56SLongpeng(Mike) }
82f0d92b56SLongpeng(Mike)
83f0d92b56SLongpeng(Mike) afalg->opfd = qemu_accept(afalg->tfmfd, NULL, 0);
84f0d92b56SLongpeng(Mike) if (afalg->opfd == -1) {
85f0d92b56SLongpeng(Mike) error_setg_errno(errp, errno, "Failed to accept socket");
86f0d92b56SLongpeng(Mike) goto error;
87f0d92b56SLongpeng(Mike) }
88f0d92b56SLongpeng(Mike)
89f0d92b56SLongpeng(Mike) return afalg;
90f0d92b56SLongpeng(Mike)
91f0d92b56SLongpeng(Mike) error:
92f0d92b56SLongpeng(Mike) qcrypto_afalg_comm_free(afalg);
93f0d92b56SLongpeng(Mike) return NULL;
94f0d92b56SLongpeng(Mike) }
95f0d92b56SLongpeng(Mike)
qcrypto_afalg_comm_free(QCryptoAFAlgo * afalg)96*8f525028SMarkus Armbruster void qcrypto_afalg_comm_free(QCryptoAFAlgo *afalg)
97f0d92b56SLongpeng(Mike) {
98f0d92b56SLongpeng(Mike) if (!afalg) {
99f0d92b56SLongpeng(Mike) return;
100f0d92b56SLongpeng(Mike) }
101f0d92b56SLongpeng(Mike)
102f0d92b56SLongpeng(Mike) if (afalg->msg) {
103f0d92b56SLongpeng(Mike) g_free(afalg->msg->msg_control);
104f0d92b56SLongpeng(Mike) g_free(afalg->msg);
105f0d92b56SLongpeng(Mike) }
106f0d92b56SLongpeng(Mike)
107f0d92b56SLongpeng(Mike) if (afalg->tfmfd != -1) {
10825657fc6SMarc-André Lureau close(afalg->tfmfd);
109f0d92b56SLongpeng(Mike) }
110f0d92b56SLongpeng(Mike)
111f0d92b56SLongpeng(Mike) if (afalg->opfd != -1) {
11225657fc6SMarc-André Lureau close(afalg->opfd);
113f0d92b56SLongpeng(Mike) }
114f0d92b56SLongpeng(Mike)
115f0d92b56SLongpeng(Mike) g_free(afalg);
116f0d92b56SLongpeng(Mike) }
117