1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 #include <fcntl.h> 17 #include <strings.h> 18 #include <unistd.h> 19 #include <errno.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 23 #include "cryptotest.h" 24 25 struct crypto_op { 26 char *in; 27 char *out; 28 char *key; 29 char *param; 30 31 size_t inlen; 32 size_t outlen; 33 size_t keylen; 34 size_t paramlen; 35 size_t updatelen; 36 37 char *mechname; 38 39 /* internal */ 40 crypto_mech_type_t mech; 41 crypto_session_id_t hsession; 42 crypto_func_group_t fg; 43 }; 44 45 static int fd; 46 static const char CRYPTO_DEVICE[] = "/dev/crypto"; 47 48 int 49 kcf_do_ioctl(int opcode, uint_t *arg, char *opstr) 50 { 51 int ret; 52 53 while ((ret = ioctl(fd, opcode, arg)) < 0) { 54 if (errno != EINTR) 55 break; 56 } 57 58 if (ret < 0 || *arg != CRYPTO_SUCCESS) 59 (void) fprintf(stderr, "%s: Error = %d %d 0x%02x\n", 60 (opstr == NULL) ? "ioctl" : opstr, 61 ret, errno, *arg); 62 63 if (ret < 0) 64 return (errno); 65 66 return (*arg); 67 } 68 69 crypto_op_t * 70 cryptotest_init(cryptotest_t *arg, crypto_func_group_t fg) 71 { 72 crypto_op_t *op = malloc(sizeof (*op)); 73 74 if (op == NULL) 75 return (NULL); 76 77 while ((fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) { 78 if (errno != EINTR) 79 return (NULL); 80 } 81 82 op->in = (char *)arg->in; 83 op->out = (char *)arg->out; 84 op->key = (char *)arg->key; 85 op->param = (char *)arg->param; 86 87 op->inlen = arg->inlen; 88 op->outlen = arg->outlen; 89 op->keylen = arg->keylen * 8; /* kcf uses keylen in bits */ 90 op->paramlen = arg->plen; 91 op->updatelen = arg->updatelen; 92 93 op->mechname = arg->mechname; 94 95 op->hsession = CRYPTO_INVALID_SESSION; 96 op->fg = fg; 97 98 if (op->out == NULL) 99 op->outlen = op->inlen; 100 return (op); 101 } 102 103 int 104 cryptotest_close_session(crypto_session_id_t session) 105 { 106 crypto_close_session_t cs; 107 108 cs.cs_session = session; 109 return (kcf_do_ioctl(CRYPTO_CLOSE_SESSION, (uint_t *)&cs, "session")); 110 } 111 112 int 113 cryptotest_close(crypto_op_t *op) 114 { 115 if (op->hsession != CRYPTO_INVALID_SESSION) 116 (void) cryptotest_close_session(op->hsession); 117 free(op); 118 if (fd >= 0) 119 return (close(fd)); 120 return (0); 121 } 122 123 int 124 get_mech_info(crypto_op_t *op) 125 { 126 crypto_get_mechanism_number_t get_number; 127 128 bzero(&get_number, sizeof (get_number)); 129 130 get_number.pn_mechanism_string = op->mechname; 131 get_number.pn_mechanism_len = strlen(op->mechname) + 1; 132 133 if (kcf_do_ioctl(CRYPTO_GET_MECHANISM_NUMBER, 134 (uint_t *)&get_number, "get_mech_info") != CRYPTO_SUCCESS) { 135 (void) fprintf(stderr, "failed to resolve mechanism name %s\n", 136 op->mechname); 137 (void) cryptotest_close(op); 138 return (CTEST_NAME_RESOLVE_FAILED); 139 } 140 op->mech = get_number.pn_internal_number; 141 return (CRYPTO_SUCCESS); 142 } 143 144 int 145 get_hsession_by_mech(crypto_op_t *op) 146 { 147 crypto_by_mech_t mech; 148 int rv; 149 150 mech.mech_keylen = op->keylen; 151 mech.mech_type = op->mech; 152 mech.mech_fg = op->fg; 153 154 rv = kcf_do_ioctl(CRYPTO_GET_PROVIDER_BY_MECH, (uint_t *)&mech, 155 "get_hsession_by_mech"); 156 157 if (rv != 0 || mech.rv != CRYPTO_SUCCESS) { 158 (void) fprintf(stderr, 159 "could not find provider for mechanism %llu\n", 160 mech.mech_type); 161 (void) cryptotest_close(op); 162 return (CTEST_MECH_NO_PROVIDER); 163 } 164 165 op->hsession = mech.session_id; 166 167 return (CRYPTO_SUCCESS); 168 } 169 170 /* 171 * CRYPTO_MAC_* functions 172 */ 173 int 174 mac_init(crypto_op_t *op) 175 { 176 crypto_mac_init_t init; 177 178 bzero((void *)&init, sizeof (init)); 179 180 init.mi_session = op->hsession; 181 182 init.mi_key.ck_data = op->key; 183 init.mi_key.ck_format = CRYPTO_KEY_RAW; /* must be this */ 184 init.mi_key.ck_length = op->keylen; 185 186 init.mi_mech.cm_type = op->mech; 187 init.mi_mech.cm_param = NULL; 188 init.mi_mech.cm_param_len = 0; 189 190 return (kcf_do_ioctl(CRYPTO_MAC_INIT, (uint_t *)&init, "init")); 191 } 192 193 int 194 mac_single(crypto_op_t *op) 195 { 196 crypto_mac_t mac; 197 198 bzero(&mac, sizeof (mac)); 199 mac.cm_session = op->hsession; 200 mac.cm_datalen = op->inlen; 201 mac.cm_databuf = op->in; 202 mac.cm_maclen = op->outlen; 203 mac.cm_macbuf = op->out; 204 205 return (kcf_do_ioctl(CRYPTO_MAC, (uint_t *)&mac, "single")); 206 } 207 208 int 209 mac_update(crypto_op_t *op, int offset) 210 { 211 crypto_mac_update_t update; 212 213 bzero((void *)&update, sizeof (update)); 214 215 update.mu_session = op->hsession; 216 update.mu_databuf = op->in + offset; 217 update.mu_datalen = op->updatelen; 218 219 return (kcf_do_ioctl(CRYPTO_MAC_UPDATE, (uint_t *)&update, "update")); 220 } 221 222 int 223 mac_final(crypto_op_t *op) 224 { 225 crypto_mac_final_t final; 226 227 bzero((void *)&final, sizeof (final)); 228 229 final.mf_session = op->hsession; 230 final.mf_maclen = op->outlen; 231 final.mf_macbuf = op->out; 232 233 return (kcf_do_ioctl(CRYPTO_MAC_FINAL, (uint_t *)&final, "final")); 234 } 235 236 237 /* 238 * CRYPTO_ENCRYPT_* functions 239 */ 240 241 int 242 encrypt_init(crypto_op_t *op) 243 { 244 crypto_encrypt_init_t init; 245 246 bzero((void *)&init, sizeof (init)); 247 248 init.ei_session = op->hsession; 249 250 init.ei_key.ck_data = op->key; 251 init.ei_key.ck_format = CRYPTO_KEY_RAW; /* must be this */ 252 init.ei_key.ck_length = op->keylen; 253 254 init.ei_mech.cm_type = op->mech; 255 init.ei_mech.cm_param = op->param; 256 init.ei_mech.cm_param_len = op->paramlen; 257 258 return (kcf_do_ioctl(CRYPTO_ENCRYPT_INIT, (uint_t *)&init, "init")); 259 } 260 261 int 262 encrypt_single(crypto_op_t *op) 263 { 264 crypto_encrypt_t encrypt; 265 266 bzero(&encrypt, sizeof (encrypt)); 267 encrypt.ce_session = op->hsession; 268 encrypt.ce_datalen = op->inlen; 269 encrypt.ce_databuf = op->in; 270 encrypt.ce_encrlen = op->outlen; 271 encrypt.ce_encrbuf = op->out; 272 273 return (kcf_do_ioctl(CRYPTO_ENCRYPT, (uint_t *)&encrypt, "single")); 274 } 275 276 int 277 encrypt_update(crypto_op_t *op, int offset, size_t *encrlen) 278 { 279 crypto_encrypt_update_t update; 280 int ret; 281 bzero((void *)&update, sizeof (update)); 282 283 update.eu_session = op->hsession; 284 update.eu_databuf = op->in + offset; 285 update.eu_datalen = op->updatelen; 286 update.eu_encrlen = op->outlen - *encrlen; 287 update.eu_encrbuf = op->out + *encrlen; 288 289 ret = kcf_do_ioctl(CRYPTO_ENCRYPT_UPDATE, (uint_t *)&update, "update"); 290 *encrlen += update.eu_encrlen; 291 return (ret); 292 } 293 294 int 295 encrypt_final(crypto_op_t *op, size_t encrlen) 296 { 297 crypto_encrypt_final_t final; 298 299 bzero((void *)&final, sizeof (final)); 300 301 final.ef_session = op->hsession; 302 final.ef_encrlen = op->outlen - encrlen; 303 final.ef_encrbuf = op->out + encrlen; 304 305 return (kcf_do_ioctl(CRYPTO_ENCRYPT_FINAL, (uint_t *)&final, "final")); 306 } 307 308 /* 309 * CRYPTO_DECRYPT_* functions 310 */ 311 312 int 313 decrypt_init(crypto_op_t *op) 314 { 315 crypto_decrypt_init_t init; 316 317 bzero((void *)&init, sizeof (init)); 318 319 init.di_session = op->hsession; 320 321 init.di_key.ck_data = op->key; 322 init.di_key.ck_format = CRYPTO_KEY_RAW; /* must be this */ 323 init.di_key.ck_length = op->keylen; 324 325 init.di_mech.cm_type = op->mech; 326 init.di_mech.cm_param = op->param; 327 init.di_mech.cm_param_len = op->paramlen; 328 329 return (kcf_do_ioctl(CRYPTO_DECRYPT_INIT, (uint_t *)&init, "init")); 330 } 331 332 int 333 decrypt_single(crypto_op_t *op) 334 { 335 crypto_decrypt_t decrypt; 336 337 bzero(&decrypt, sizeof (decrypt)); 338 decrypt.cd_session = op->hsession; 339 decrypt.cd_datalen = op->outlen; 340 decrypt.cd_databuf = op->out; 341 decrypt.cd_encrlen = op->inlen; 342 decrypt.cd_encrbuf = op->in; 343 344 return (kcf_do_ioctl(CRYPTO_DECRYPT, (uint_t *)&decrypt, "single")); 345 } 346 347 int 348 decrypt_update(crypto_op_t *op, int offset, size_t *encrlen) 349 { 350 crypto_decrypt_update_t update; 351 int ret; 352 353 bzero((void *)&update, sizeof (update)); 354 355 update.du_session = op->hsession; 356 update.du_databuf = op->out + *encrlen; 357 update.du_datalen = op->outlen - *encrlen; 358 update.du_encrlen = op->updatelen; 359 update.du_encrbuf = op->in + offset; 360 361 ret = kcf_do_ioctl(CRYPTO_DECRYPT_UPDATE, (uint_t *)&update, "update"); 362 *encrlen += update.du_datalen; 363 return (ret); 364 } 365 366 int 367 decrypt_final(crypto_op_t *op, size_t encrlen) 368 { 369 crypto_decrypt_final_t final; 370 371 bzero((void *)&final, sizeof (final)); 372 373 final.df_session = op->hsession; 374 final.df_datalen = op->outlen - encrlen; 375 final.df_databuf = op->out + encrlen; 376 377 return (kcf_do_ioctl(CRYPTO_DECRYPT_FINAL, (uint_t *)&final, "final")); 378 }