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