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 * Copyright 2018, Joyent, Inc. 15 */ 16 17 #include <fcntl.h> 18 #include <strings.h> 19 #include <unistd.h> 20 #include <errno.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 24 #include "cryptotest.h" 25 26 struct crypto_op { 27 char *in; 28 char *out; 29 char *key; 30 char *param; 31 32 size_t inlen; 33 size_t outlen; 34 size_t keylen; 35 size_t paramlen; 36 size_t updatelen; 37 38 char *mechname; 39 40 /* internal */ 41 crypto_mech_type_t mech; 42 crypto_session_id_t hsession; 43 crypto_func_group_t fg; 44 }; 45 46 static int fd; 47 static const char CRYPTO_DEVICE[] = "/dev/crypto"; 48 49 int 50 kcf_do_ioctl(int opcode, uint_t *arg, char *opstr) 51 { 52 int ret; 53 54 while ((ret = ioctl(fd, opcode, arg)) < 0) { 55 if (errno != EINTR) 56 break; 57 } 58 59 if (ret < 0 || *arg != CRYPTO_SUCCESS) 60 (void) fprintf(stderr, "%s: Error = %d %d 0x%02x\n", 61 (opstr == NULL) ? "ioctl" : opstr, 62 ret, errno, *arg); 63 64 if (ret < 0) 65 return (errno); 66 67 return (*arg); 68 } 69 70 crypto_op_t * 71 cryptotest_init(cryptotest_t *arg, crypto_func_group_t fg) 72 { 73 crypto_op_t *op = malloc(sizeof (*op)); 74 75 if (op == NULL) 76 return (NULL); 77 78 while ((fd = open(CRYPTO_DEVICE, O_RDWR)) < 0) { 79 if (errno != EINTR) { 80 free(op); 81 return (NULL); 82 } 83 } 84 85 op->in = (char *)arg->in; 86 op->out = (char *)arg->out; 87 op->key = (char *)arg->key; 88 op->param = (char *)arg->param; 89 90 op->inlen = arg->inlen; 91 op->outlen = arg->outlen; 92 op->keylen = arg->keylen * 8; /* kcf uses keylen in bits */ 93 op->paramlen = arg->plen; 94 op->updatelen = arg->updatelen; 95 96 op->mechname = arg->mechname; 97 98 op->hsession = CRYPTO_INVALID_SESSION; 99 op->fg = fg; 100 101 if (op->out == NULL) 102 op->outlen = op->inlen; 103 return (op); 104 } 105 106 int 107 cryptotest_close_session(crypto_session_id_t session) 108 { 109 crypto_close_session_t cs; 110 111 cs.cs_session = session; 112 return (kcf_do_ioctl(CRYPTO_CLOSE_SESSION, (uint_t *)&cs, "session")); 113 } 114 115 int 116 cryptotest_close(crypto_op_t *op) 117 { 118 if (op->hsession != CRYPTO_INVALID_SESSION) 119 (void) cryptotest_close_session(op->hsession); 120 free(op); 121 if (fd >= 0) 122 return (close(fd)); 123 return (0); 124 } 125 126 int 127 get_mech_info(crypto_op_t *op) 128 { 129 crypto_get_mechanism_number_t get_number; 130 131 bzero(&get_number, sizeof (get_number)); 132 133 get_number.pn_mechanism_string = op->mechname; 134 get_number.pn_mechanism_len = strlen(op->mechname) + 1; 135 136 if (kcf_do_ioctl(CRYPTO_GET_MECHANISM_NUMBER, 137 (uint_t *)&get_number, "get_mech_info") != CRYPTO_SUCCESS) { 138 (void) fprintf(stderr, "failed to resolve mechanism name %s\n", 139 op->mechname); 140 return (CTEST_NAME_RESOLVE_FAILED); 141 } 142 op->mech = get_number.pn_internal_number; 143 return (CRYPTO_SUCCESS); 144 } 145 146 int 147 get_hsession_by_mech(crypto_op_t *op) 148 { 149 crypto_by_mech_t mech; 150 int rv; 151 152 mech.mech_keylen = op->keylen; 153 mech.mech_type = op->mech; 154 mech.mech_fg = op->fg; 155 156 rv = kcf_do_ioctl(CRYPTO_GET_PROVIDER_BY_MECH, (uint_t *)&mech, 157 "get_hsession_by_mech"); 158 159 if (rv != 0 || mech.rv != CRYPTO_SUCCESS) { 160 (void) fprintf(stderr, 161 "could not find provider for mechanism %llu\n", 162 mech.mech_type); 163 return (CTEST_MECH_NO_PROVIDER); 164 } 165 166 op->hsession = mech.session_id; 167 168 return (CRYPTO_SUCCESS); 169 } 170 171 /* 172 * CRYPTO_MAC_* functions 173 */ 174 int 175 mac_init(crypto_op_t *op) 176 { 177 crypto_mac_init_t init; 178 179 bzero((void *)&init, sizeof (init)); 180 181 init.mi_session = op->hsession; 182 183 init.mi_key.ck_data = op->key; 184 init.mi_key.ck_format = CRYPTO_KEY_RAW; /* must be this */ 185 init.mi_key.ck_length = op->keylen; 186 187 init.mi_mech.cm_type = op->mech; 188 init.mi_mech.cm_param = NULL; 189 init.mi_mech.cm_param_len = 0; 190 191 return (kcf_do_ioctl(CRYPTO_MAC_INIT, (uint_t *)&init, "init")); 192 } 193 194 int 195 mac_single(crypto_op_t *op) 196 { 197 crypto_mac_t mac; 198 199 bzero(&mac, sizeof (mac)); 200 mac.cm_session = op->hsession; 201 mac.cm_datalen = op->inlen; 202 mac.cm_databuf = op->in; 203 mac.cm_maclen = op->outlen; 204 mac.cm_macbuf = op->out; 205 206 return (kcf_do_ioctl(CRYPTO_MAC, (uint_t *)&mac, "single")); 207 } 208 209 int 210 mac_update(crypto_op_t *op, int offset) 211 { 212 crypto_mac_update_t update; 213 214 bzero((void *)&update, sizeof (update)); 215 216 update.mu_session = op->hsession; 217 update.mu_databuf = op->in + offset; 218 update.mu_datalen = op->updatelen; 219 220 return (kcf_do_ioctl(CRYPTO_MAC_UPDATE, (uint_t *)&update, "update")); 221 } 222 223 int 224 mac_final(crypto_op_t *op) 225 { 226 crypto_mac_final_t final; 227 228 bzero((void *)&final, sizeof (final)); 229 230 final.mf_session = op->hsession; 231 final.mf_maclen = op->outlen; 232 final.mf_macbuf = op->out; 233 234 return (kcf_do_ioctl(CRYPTO_MAC_FINAL, (uint_t *)&final, "final")); 235 } 236 237 238 /* 239 * CRYPTO_ENCRYPT_* functions 240 */ 241 242 int 243 encrypt_init(crypto_op_t *op) 244 { 245 crypto_encrypt_init_t init; 246 247 bzero((void *)&init, sizeof (init)); 248 249 init.ei_session = op->hsession; 250 251 init.ei_key.ck_data = op->key; 252 init.ei_key.ck_format = CRYPTO_KEY_RAW; /* must be this */ 253 init.ei_key.ck_length = op->keylen; 254 255 init.ei_mech.cm_type = op->mech; 256 init.ei_mech.cm_param = op->param; 257 init.ei_mech.cm_param_len = op->paramlen; 258 259 return (kcf_do_ioctl(CRYPTO_ENCRYPT_INIT, (uint_t *)&init, "init")); 260 } 261 262 int 263 encrypt_single(crypto_op_t *op) 264 { 265 crypto_encrypt_t encrypt; 266 267 bzero(&encrypt, sizeof (encrypt)); 268 encrypt.ce_session = op->hsession; 269 encrypt.ce_datalen = op->inlen; 270 encrypt.ce_databuf = op->in; 271 encrypt.ce_encrlen = op->outlen; 272 encrypt.ce_encrbuf = op->out; 273 274 return (kcf_do_ioctl(CRYPTO_ENCRYPT, (uint_t *)&encrypt, "single")); 275 } 276 277 int 278 encrypt_update(crypto_op_t *op, int offset, size_t *encrlen) 279 { 280 crypto_encrypt_update_t update; 281 int ret; 282 bzero((void *)&update, sizeof (update)); 283 284 update.eu_session = op->hsession; 285 update.eu_databuf = op->in + offset; 286 update.eu_datalen = op->updatelen; 287 update.eu_encrlen = op->outlen - *encrlen; 288 update.eu_encrbuf = op->out + *encrlen; 289 290 ret = kcf_do_ioctl(CRYPTO_ENCRYPT_UPDATE, (uint_t *)&update, "update"); 291 *encrlen += update.eu_encrlen; 292 return (ret); 293 } 294 295 int 296 encrypt_final(crypto_op_t *op, size_t encrlen) 297 { 298 crypto_encrypt_final_t final; 299 300 bzero((void *)&final, sizeof (final)); 301 302 final.ef_session = op->hsession; 303 final.ef_encrlen = op->outlen - encrlen; 304 final.ef_encrbuf = op->out + encrlen; 305 306 return (kcf_do_ioctl(CRYPTO_ENCRYPT_FINAL, (uint_t *)&final, "final")); 307 } 308 309 /* 310 * CRYPTO_DECRYPT_* functions 311 */ 312 313 int 314 decrypt_init(crypto_op_t *op) 315 { 316 crypto_decrypt_init_t init; 317 318 bzero((void *)&init, sizeof (init)); 319 320 init.di_session = op->hsession; 321 322 init.di_key.ck_data = op->key; 323 init.di_key.ck_format = CRYPTO_KEY_RAW; /* must be this */ 324 init.di_key.ck_length = op->keylen; 325 326 init.di_mech.cm_type = op->mech; 327 init.di_mech.cm_param = op->param; 328 init.di_mech.cm_param_len = op->paramlen; 329 330 return (kcf_do_ioctl(CRYPTO_DECRYPT_INIT, (uint_t *)&init, "init")); 331 } 332 333 int 334 decrypt_single(crypto_op_t *op) 335 { 336 crypto_decrypt_t decrypt; 337 338 bzero(&decrypt, sizeof (decrypt)); 339 decrypt.cd_session = op->hsession; 340 decrypt.cd_datalen = op->outlen; 341 decrypt.cd_databuf = op->out; 342 decrypt.cd_encrlen = op->inlen; 343 decrypt.cd_encrbuf = op->in; 344 345 return (kcf_do_ioctl(CRYPTO_DECRYPT, (uint_t *)&decrypt, "single")); 346 } 347 348 int 349 decrypt_update(crypto_op_t *op, int offset, size_t *encrlen) 350 { 351 crypto_decrypt_update_t update; 352 int ret; 353 354 bzero((void *)&update, sizeof (update)); 355 356 update.du_session = op->hsession; 357 update.du_databuf = op->out + *encrlen; 358 update.du_datalen = op->outlen - *encrlen; 359 update.du_encrlen = op->updatelen; 360 update.du_encrbuf = op->in + offset; 361 362 ret = kcf_do_ioctl(CRYPTO_DECRYPT_UPDATE, (uint_t *)&update, "update"); 363 *encrlen += update.du_datalen; 364 return (ret); 365 } 366 367 int 368 decrypt_final(crypto_op_t *op, size_t encrlen) 369 { 370 crypto_decrypt_final_t final; 371 372 bzero((void *)&final, sizeof (final)); 373 374 final.df_session = op->hsession; 375 final.df_datalen = op->outlen - encrlen; 376 final.df_databuf = op->out + encrlen; 377 378 return (kcf_do_ioctl(CRYPTO_DECRYPT_FINAL, (uint_t *)&final, "final")); 379 } 380 381 int 382 digest_init(crypto_op_t *op) 383 { 384 crypto_digest_init_t init; 385 386 bzero(&init, sizeof (init)); 387 388 init.di_session = op->hsession; 389 390 init.di_mech.cm_type = op->mech; 391 init.di_mech.cm_param = NULL; 392 init.di_mech.cm_param_len = 0; 393 394 return (kcf_do_ioctl(CRYPTO_DIGEST_INIT, (uint_t *)&init, "init")); 395 } 396 397 int 398 digest_single(crypto_op_t *op) 399 { 400 crypto_digest_t digest; 401 402 bzero(&digest, sizeof (digest)); 403 404 digest.cd_session = op->hsession; 405 406 digest.cd_datalen = op->inlen; 407 digest.cd_databuf = op->in; 408 digest.cd_digestlen = op->outlen; 409 digest.cd_digestbuf = op->out; 410 411 return (kcf_do_ioctl(CRYPTO_DIGEST, (uint_t *)&digest, "digest")); 412 } 413 414 int 415 digest_update(crypto_op_t *op, int offset) 416 { 417 crypto_digest_update_t update; 418 419 bzero(&update, sizeof (update)); 420 421 update.du_session = op->hsession; 422 423 update.du_datalen = op->updatelen; 424 update.du_databuf = op->in + offset; 425 426 return (kcf_do_ioctl(CRYPTO_DIGEST_UPDATE, (uint_t *)&update, 427 "update")); 428 } 429 430 int 431 digest_final(crypto_op_t *op) 432 { 433 crypto_digest_final_t final; 434 435 bzero(&final, sizeof (final)); 436 437 final.df_session = op->hsession; 438 439 final.df_digestlen = op->outlen; 440 final.df_digestbuf = op->out; 441 442 return (kcf_do_ioctl(CRYPTO_DIGEST_FINAL, (uint_t *)&final, "final")); 443 } 444 void 445 ccm_init_params(void *buf, ulong_t ulDataLen, uchar_t *pNonce, 446 ulong_t ulNonceLen, uchar_t *pAAD, ulong_t ulAADLen, ulong_t ulMACLen) 447 { 448 CK_AES_CCM_PARAMS *pp = buf; 449 450 pp->ulDataSize = ulDataLen; 451 pp->nonce = pNonce; 452 pp->ulNonceSize = ulNonceLen; 453 pp->authData = pAAD; 454 pp->ulAuthDataSize = ulAADLen; 455 pp->ulMACSize = ulMACLen; 456 } 457 458 size_t 459 ccm_param_len(void) 460 { 461 return (sizeof (CK_AES_CCM_PARAMS)); 462 }