1/*
2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3 * Copyright (c) 2017 The strace developers.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "defs.h"
30
31#ifdef HAVE_LINUX_CRYPTOUSER_H
32
33# include "netlink.h"
34# include "nlattr.h"
35# include "print_fields.h"
36
37# include <linux/cryptouser.h>
38
39# include "xlat/crypto_nl_attrs.h"
40
41static bool
42decode_crypto_report_generic(struct tcb *const tcp,
43			     const kernel_ulong_t addr,
44			     const unsigned int len,
45			     const void *const opaque_data)
46{
47	tprints("{type=");
48	printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED);
49	tprints("}");
50
51	return true;
52}
53
54static bool
55decode_crypto_report_hash(struct tcb *const tcp,
56			  const kernel_ulong_t addr,
57			  const unsigned int len,
58			  const void *const opaque_data)
59{
60# ifdef HAVE_STRUCT_CRYPTO_REPORT_HASH
61	struct crypto_report_hash rhash;
62
63	if (len < sizeof(rhash))
64		printstrn(tcp, addr, len);
65	else if (!umove_or_printaddr(tcp, addr, &rhash)) {
66		PRINT_FIELD_CSTRING("{", rhash, type);
67		PRINT_FIELD_U(", ", rhash, blocksize);
68		PRINT_FIELD_U(", ", rhash, digestsize);
69		tprints("}");
70	}
71# else
72	printstrn(tcp, addr, len);
73# endif
74
75	return true;
76}
77
78static bool
79decode_crypto_report_blkcipher(struct tcb *const tcp,
80			       const kernel_ulong_t addr,
81			       const unsigned int len,
82			       const void *const opaque_data)
83{
84# ifdef HAVE_STRUCT_CRYPTO_REPORT_BLKCIPHER
85	struct crypto_report_blkcipher rblkcipher;
86
87	if (len < sizeof(rblkcipher))
88		printstrn(tcp, addr, len);
89	else if (!umove_or_printaddr(tcp, addr, &rblkcipher)) {
90		PRINT_FIELD_CSTRING("{", rblkcipher, type);
91		PRINT_FIELD_CSTRING(", ", rblkcipher, geniv);
92		PRINT_FIELD_U(", ", rblkcipher, blocksize);
93		PRINT_FIELD_U(", ", rblkcipher, min_keysize);
94		PRINT_FIELD_U(", ", rblkcipher, max_keysize);
95		PRINT_FIELD_U(", ", rblkcipher, ivsize);
96		tprints("}");
97	}
98# else
99	printstrn(tcp, addr, len);
100# endif
101
102	return true;
103}
104
105static bool
106decode_crypto_report_aead(struct tcb *const tcp,
107			  const kernel_ulong_t addr,
108			  const unsigned int len,
109			  const void *const opaque_data)
110{
111# ifdef HAVE_STRUCT_CRYPTO_REPORT_AEAD
112	struct crypto_report_aead raead;
113
114	if (len < sizeof(raead))
115		printstrn(tcp, addr, len);
116	else if (!umove_or_printaddr(tcp, addr, &raead)) {
117		PRINT_FIELD_CSTRING("{", raead, type);
118		PRINT_FIELD_CSTRING(", ", raead, geniv);
119		PRINT_FIELD_U(", ", raead, blocksize);
120		PRINT_FIELD_U(", ", raead, maxauthsize);
121		PRINT_FIELD_U(", ", raead, ivsize);
122		tprints("}");
123	}
124# else
125	printstrn(tcp, addr, len);
126# endif
127
128	return true;
129}
130
131static bool
132decode_crypto_report_rng(struct tcb *const tcp,
133			 const kernel_ulong_t addr,
134			 const unsigned int len,
135			 const void *const opaque_data)
136{
137# ifdef HAVE_STRUCT_CRYPTO_REPORT_RNG
138	struct crypto_report_rng rrng;
139
140	if (len < sizeof(rrng))
141		printstrn(tcp, addr, len);
142	else if (!umove_or_printaddr(tcp, addr, &rrng)) {
143		PRINT_FIELD_CSTRING("{", rrng, type);
144		PRINT_FIELD_U(", ", rrng, seedsize);
145		tprints("}");
146	}
147# else
148	printstrn(tcp, addr, len);
149# endif
150
151	return true;
152}
153
154static bool
155decode_crypto_report_cipher(struct tcb *const tcp,
156			    const kernel_ulong_t addr,
157			    const unsigned int len,
158			    const void *const opaque_data)
159{
160# ifdef HAVE_STRUCT_CRYPTO_REPORT_CIPHER
161	struct crypto_report_cipher rcipher;
162
163	if (len < sizeof(rcipher))
164		printstrn(tcp, addr, len);
165	else if (!umove_or_printaddr(tcp, addr, &rcipher)) {
166		PRINT_FIELD_CSTRING("{", rcipher, type);
167		PRINT_FIELD_U(", ", rcipher, blocksize);
168		PRINT_FIELD_U(", ", rcipher, min_keysize);
169		PRINT_FIELD_U(", ", rcipher, max_keysize);
170		tprints("}");
171	}
172# else
173	printstrn(tcp, addr, len);
174# endif
175
176	return true;
177}
178
179static const nla_decoder_t crypto_user_alg_nla_decoders[] = {
180	[CRYPTOCFGA_PRIORITY_VAL]	= decode_nla_u32,
181	[CRYPTOCFGA_REPORT_LARVAL]	= decode_crypto_report_generic,
182	[CRYPTOCFGA_REPORT_HASH]	= decode_crypto_report_hash,
183	[CRYPTOCFGA_REPORT_BLKCIPHER]	= decode_crypto_report_blkcipher,
184	[CRYPTOCFGA_REPORT_AEAD]	= decode_crypto_report_aead,
185	[CRYPTOCFGA_REPORT_COMPRESS]	= decode_crypto_report_generic,
186	[CRYPTOCFGA_REPORT_RNG]		= decode_crypto_report_rng,
187	[CRYPTOCFGA_REPORT_CIPHER]	= decode_crypto_report_cipher,
188	[CRYPTOCFGA_REPORT_AKCIPHER]	= decode_crypto_report_generic,
189	[CRYPTOCFGA_REPORT_KPP]		= decode_crypto_report_generic,
190	[CRYPTOCFGA_REPORT_ACOMP]	= decode_crypto_report_generic
191};
192
193static void
194decode_crypto_user_alg(struct tcb *const tcp,
195		       const kernel_ulong_t addr,
196		       const unsigned int len)
197{
198	struct crypto_user_alg alg;
199
200	if (len < sizeof(alg))
201		printstrn(tcp, addr, len);
202	else if (!umove_or_printaddr(tcp, addr, &alg)) {
203		PRINT_FIELD_CSTRING("{", alg, cru_name);
204		PRINT_FIELD_CSTRING(", ", alg, cru_driver_name);
205		PRINT_FIELD_CSTRING(", ", alg, cru_module_name);
206		PRINT_FIELD_X(", ", alg, cru_type);
207		PRINT_FIELD_X(", ", alg, cru_mask);
208		PRINT_FIELD_U(", ", alg, cru_refcnt);
209		PRINT_FIELD_X(", ", alg, cru_flags);
210		tprints("}");
211
212		const size_t offset = NLMSG_ALIGN(sizeof(alg));
213		if (len > offset) {
214			tprints(", ");
215			decode_nlattr(tcp, addr + offset, len - offset,
216				      crypto_nl_attrs, "CRYPTOCFGA_???",
217				      crypto_user_alg_nla_decoders,
218				      ARRAY_SIZE(crypto_user_alg_nla_decoders),
219				      NULL);
220		}
221	}
222}
223
224bool
225decode_netlink_crypto(struct tcb *const tcp,
226		      const struct nlmsghdr *const nlmsghdr,
227		      const kernel_ulong_t addr,
228		      const unsigned int len)
229{
230	switch (nlmsghdr->nlmsg_type) {
231	case CRYPTO_MSG_NEWALG:
232	case CRYPTO_MSG_DELALG:
233	case CRYPTO_MSG_UPDATEALG:
234	case CRYPTO_MSG_GETALG:
235		decode_crypto_user_alg(tcp, addr, len);
236		break;
237	default:
238		return false;
239	}
240
241	return true;
242}
243
244#endif /* HAVE_LINUX_CRYPTOUSER_H */
245