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