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 }