Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/cryptmod.c
+++ new/usr/src/uts/common/io/cryptmod.c
1 1 /*
2 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
3 3 * Use is subject to license terms.
4 4 *
5 5 * STREAMS Crypto Module
6 6 *
7 7 * This module is used to facilitate Kerberos encryption
8 8 * operations for the telnet daemon and rlogin daemon.
9 9 * Because the Solaris telnet and rlogin daemons run mostly
10 10 * in-kernel via 'telmod' and 'rlmod', this module must be
11 11 * pushed on the STREAM *below* telmod or rlmod.
12 12 *
13 13 * Parts of the 3DES key derivation code are covered by the
14 14 * following copyright.
15 15 *
16 16 * Copyright (C) 1998 by the FundsXpress, INC.
17 17 *
18 18 * All rights reserved.
19 19 *
20 20 * Export of this software from the United States of America may require
21 21 * a specific license from the United States Government. It is the
22 22 * responsibility of any person or organization contemplating export to
23 23 * obtain such a license before exporting.
24 24 *
25 25 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
26 26 * distribute this software and its documentation for any purpose and
27 27 * without fee is hereby granted, provided that the above copyright
28 28 * notice appear in all copies and that both that copyright notice and
29 29 * this permission notice appear in supporting documentation, and that
30 30 * the name of FundsXpress. not be used in advertising or publicity pertaining
31 31 * to distribution of the software without specific, written prior
32 32 * permission. FundsXpress makes no representations about the suitability of
33 33 * this software for any purpose. It is provided "as is" without express
34 34 * or implied warranty.
35 35 *
36 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
37 37 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
38 38 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
39 39 */
40 40
41 41 #include <sys/types.h>
42 42 #include <sys/sysmacros.h>
43 43 #include <sys/errno.h>
44 44 #include <sys/debug.h>
45 45 #include <sys/time.h>
46 46 #include <sys/stropts.h>
47 47 #include <sys/stream.h>
48 48 #include <sys/strsubr.h>
49 49 #include <sys/strlog.h>
50 50 #include <sys/cmn_err.h>
51 51 #include <sys/conf.h>
52 52 #include <sys/sunddi.h>
53 53 #include <sys/kmem.h>
54 54 #include <sys/strsun.h>
55 55 #include <sys/random.h>
56 56 #include <sys/types.h>
57 57 #include <sys/byteorder.h>
58 58 #include <sys/cryptmod.h>
59 59 #include <sys/crc32.h>
60 60 #include <sys/policy.h>
61 61
62 62 #include <sys/crypto/api.h>
63 63
64 64 /*
65 65 * Function prototypes.
66 66 */
67 67 static int cryptmodopen(queue_t *, dev_t *, int, int, cred_t *);
68 68 static void cryptmodrput(queue_t *, mblk_t *);
69 69 static void cryptmodwput(queue_t *, mblk_t *);
70 70 static int cryptmodclose(queue_t *);
71 71 static int cryptmodwsrv(queue_t *);
72 72 static int cryptmodrsrv(queue_t *);
73 73
74 74 static mblk_t *do_encrypt(queue_t *q, mblk_t *mp);
75 75 static mblk_t *do_decrypt(queue_t *q, mblk_t *mp);
76 76
77 77 #define CRYPTMOD_ID 5150
78 78
79 79 #define CFB_BLKSZ 8
80 80
81 81 #define K5CLENGTH 5
82 82
83 83 static struct module_info cryptmod_minfo = {
84 84 CRYPTMOD_ID, /* mi_idnum */
85 85 "cryptmod", /* mi_idname */
86 86 0, /* mi_minpsz */
87 87 INFPSZ, /* mi_maxpsz */
88 88 65536, /* mi_hiwat */
89 89 1024 /* mi_lowat */
90 90 };
91 91
92 92 static struct qinit cryptmod_rinit = {
93 93 (int (*)())cryptmodrput, /* qi_putp */
94 94 cryptmodrsrv, /* qi_svc */
95 95 cryptmodopen, /* qi_qopen */
96 96 cryptmodclose, /* qi_qclose */
97 97 NULL, /* qi_qadmin */
98 98 &cryptmod_minfo, /* qi_minfo */
99 99 NULL /* qi_mstat */
100 100 };
101 101
102 102 static struct qinit cryptmod_winit = {
103 103 (int (*)())cryptmodwput, /* qi_putp */
104 104 cryptmodwsrv, /* qi_srvp */
105 105 NULL, /* qi_qopen */
106 106 NULL, /* qi_qclose */
107 107 NULL, /* qi_qadmin */
108 108 &cryptmod_minfo, /* qi_minfo */
109 109 NULL /* qi_mstat */
110 110 };
111 111
112 112 static struct streamtab cryptmod_info = {
113 113 &cryptmod_rinit, /* st_rdinit */
114 114 &cryptmod_winit, /* st_wrinit */
115 115 NULL, /* st_muxrinit */
116 116 NULL /* st_muxwinit */
117 117 };
118 118
119 119 typedef struct {
120 120 uint_t hash_len;
121 121 uint_t confound_len;
122 122 int (*hashfunc)();
123 123 } hash_info_t;
124 124
125 125 #define MAX_CKSUM_LEN 20
126 126 #define CONFOUNDER_LEN 8
127 127
128 128 #define SHA1_HASHSIZE 20
129 129 #define MD5_HASHSIZE 16
130 130 #define CRC32_HASHSIZE 4
131 131 #define MSGBUF_SIZE 4096
132 132 #define CONFOUNDER_BYTES 128
133 133
134 134
135 135 static int crc32_calc(uchar_t *, uchar_t *, uint_t);
136 136 static int md5_calc(uchar_t *, uchar_t *, uint_t);
137 137 static int sha1_calc(uchar_t *, uchar_t *, uint_t);
138 138
139 139 static hash_info_t null_hash = {0, 0, NULL};
140 140 static hash_info_t crc32_hash = {CRC32_HASHSIZE, CONFOUNDER_LEN, crc32_calc};
141 141 static hash_info_t md5_hash = {MD5_HASHSIZE, CONFOUNDER_LEN, md5_calc};
142 142 static hash_info_t sha1_hash = {SHA1_HASHSIZE, CONFOUNDER_LEN, sha1_calc};
143 143
144 144 static crypto_mech_type_t sha1_hmac_mech = CRYPTO_MECH_INVALID;
145 145 static crypto_mech_type_t md5_hmac_mech = CRYPTO_MECH_INVALID;
146 146 static crypto_mech_type_t sha1_hash_mech = CRYPTO_MECH_INVALID;
147 147 static crypto_mech_type_t md5_hash_mech = CRYPTO_MECH_INVALID;
148 148
149 149 static int kef_crypt(struct cipher_data_t *, void *,
150 150 crypto_data_format_t, size_t, int);
151 151 static mblk_t *
152 152 arcfour_hmac_md5_encrypt(queue_t *, struct tmodinfo *,
153 153 mblk_t *, hash_info_t *);
154 154 static mblk_t *
155 155 arcfour_hmac_md5_decrypt(queue_t *, struct tmodinfo *,
156 156 mblk_t *, hash_info_t *);
157 157
158 158 static int
159 159 do_hmac(crypto_mech_type_t, crypto_key_t *, char *, int, char *, int);
160 160
161 161 /*
162 162 * This is the loadable module wrapper.
163 163 */
164 164 #include <sys/modctl.h>
165 165
166 166 static struct fmodsw fsw = {
167 167 "cryptmod",
168 168 &cryptmod_info,
169 169 D_MP | D_MTQPAIR
170 170 };
171 171
172 172 /*
↓ open down ↓ |
172 lines elided |
↑ open up ↑ |
173 173 * Module linkage information for the kernel.
174 174 */
175 175 static struct modlstrmod modlstrmod = {
176 176 &mod_strmodops,
177 177 "STREAMS encryption module",
178 178 &fsw
179 179 };
180 180
181 181 static struct modlinkage modlinkage = {
182 182 MODREV_1,
183 - &modlstrmod,
184 - NULL
183 + { &modlstrmod, NULL }
185 184 };
186 185
187 186 int
188 187 _init(void)
189 188 {
190 189 return (mod_install(&modlinkage));
191 190 }
192 191
193 192 int
194 193 _fini(void)
195 194 {
196 195 return (mod_remove(&modlinkage));
197 196 }
198 197
199 198 int
200 199 _info(struct modinfo *modinfop)
201 200 {
202 201 return (mod_info(&modlinkage, modinfop));
203 202 }
204 203
205 204 static void
206 205 cleanup(struct cipher_data_t *cd)
207 206 {
208 207 if (cd->key != NULL) {
209 208 bzero(cd->key, cd->keylen);
210 209 kmem_free(cd->key, cd->keylen);
211 210 cd->key = NULL;
212 211 }
213 212
214 213 if (cd->ckey != NULL) {
215 214 /*
216 215 * ckey is a crypto_key_t structure which references
217 216 * "cd->key" for its raw key data. Since that was already
218 217 * cleared out, we don't need another "bzero" here.
219 218 */
220 219 kmem_free(cd->ckey, sizeof (crypto_key_t));
221 220 cd->ckey = NULL;
222 221 }
223 222
224 223 if (cd->block != NULL) {
225 224 kmem_free(cd->block, cd->blocklen);
226 225 cd->block = NULL;
227 226 }
228 227
229 228 if (cd->saveblock != NULL) {
230 229 kmem_free(cd->saveblock, cd->blocklen);
231 230 cd->saveblock = NULL;
232 231 }
233 232
234 233 if (cd->ivec != NULL) {
235 234 kmem_free(cd->ivec, cd->ivlen);
236 235 cd->ivec = NULL;
237 236 }
238 237
239 238 if (cd->d_encr_key.ck_data != NULL) {
240 239 bzero(cd->d_encr_key.ck_data, cd->keylen);
241 240 kmem_free(cd->d_encr_key.ck_data, cd->keylen);
242 241 }
243 242
244 243 if (cd->d_hmac_key.ck_data != NULL) {
245 244 bzero(cd->d_hmac_key.ck_data, cd->keylen);
246 245 kmem_free(cd->d_hmac_key.ck_data, cd->keylen);
247 246 }
248 247
249 248 if (cd->enc_tmpl != NULL)
250 249 (void) crypto_destroy_ctx_template(cd->enc_tmpl);
251 250
252 251 if (cd->hmac_tmpl != NULL)
253 252 (void) crypto_destroy_ctx_template(cd->hmac_tmpl);
254 253
255 254 if (cd->ctx != NULL) {
256 255 crypto_cancel_ctx(cd->ctx);
257 256 cd->ctx = NULL;
258 257 }
259 258 }
260 259
261 260 /* ARGSUSED */
262 261 static int
263 262 cryptmodopen(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp)
264 263 {
265 264 struct tmodinfo *tmi;
266 265 ASSERT(rq);
267 266
268 267 if (sflag != MODOPEN)
269 268 return (EINVAL);
270 269
271 270 (void) (STRLOG(CRYPTMOD_ID, 0, 5, SL_TRACE|SL_NOTE,
272 271 "cryptmodopen: opening module(PID %d)",
273 272 ddi_get_pid()));
274 273
275 274 if (rq->q_ptr != NULL) {
276 275 cmn_err(CE_WARN, "cryptmodopen: already opened");
277 276 return (0);
278 277 }
279 278
280 279 /*
281 280 * Allocate and initialize per-Stream structure.
282 281 */
283 282 tmi = (struct tmodinfo *)kmem_zalloc(sizeof (struct tmodinfo),
284 283 KM_SLEEP);
285 284
286 285 tmi->enc_data.method = CRYPT_METHOD_NONE;
287 286 tmi->dec_data.method = CRYPT_METHOD_NONE;
288 287
289 288 tmi->ready = (CRYPT_READ_READY | CRYPT_WRITE_READY);
290 289
291 290 rq->q_ptr = WR(rq)->q_ptr = tmi;
292 291
293 292 sha1_hmac_mech = crypto_mech2id(SUN_CKM_SHA1_HMAC);
294 293 md5_hmac_mech = crypto_mech2id(SUN_CKM_MD5_HMAC);
295 294 sha1_hash_mech = crypto_mech2id(SUN_CKM_SHA1);
296 295 md5_hash_mech = crypto_mech2id(SUN_CKM_MD5);
297 296
298 297 qprocson(rq);
299 298
300 299 return (0);
301 300 }
302 301
303 302 static int
304 303 cryptmodclose(queue_t *rq)
305 304 {
306 305 struct tmodinfo *tmi = (struct tmodinfo *)rq->q_ptr;
307 306 ASSERT(tmi);
308 307
309 308 qprocsoff(rq);
310 309
311 310 cleanup(&tmi->enc_data);
312 311 cleanup(&tmi->dec_data);
313 312
314 313 kmem_free(tmi, sizeof (struct tmodinfo));
315 314 rq->q_ptr = WR(rq)->q_ptr = NULL;
316 315
317 316 return (0);
318 317 }
319 318
320 319 /*
321 320 * plaintext_offset
322 321 *
323 322 * Calculate exactly how much space is needed in front
324 323 * of the "plaintext" in an mbuf so it can be positioned
325 324 * 1 time instead of potentially moving the data multiple
326 325 * times.
327 326 */
328 327 static int
329 328 plaintext_offset(struct cipher_data_t *cd)
330 329 {
331 330 int headspace = 0;
332 331
333 332 /* 4 byte length prepended to all RCMD msgs */
334 333 if (ANY_RCMD_MODE(cd->option_mask))
335 334 headspace += RCMD_LEN_SZ;
336 335
337 336 /* RCMD V2 mode adds an additional 4 byte plaintext length */
338 337 if (cd->option_mask & CRYPTOPT_RCMD_MODE_V2)
339 338 headspace += RCMD_LEN_SZ;
340 339
341 340 /* Need extra space for hash and counfounder */
342 341 switch (cd->method) {
343 342 case CRYPT_METHOD_DES_CBC_NULL:
344 343 headspace += null_hash.hash_len + null_hash.confound_len;
345 344 break;
346 345 case CRYPT_METHOD_DES_CBC_CRC:
347 346 headspace += crc32_hash.hash_len + crc32_hash.confound_len;
348 347 break;
349 348 case CRYPT_METHOD_DES_CBC_MD5:
350 349 headspace += md5_hash.hash_len + md5_hash.confound_len;
351 350 break;
352 351 case CRYPT_METHOD_DES3_CBC_SHA1:
353 352 headspace += sha1_hash.confound_len;
354 353 break;
355 354 case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
356 355 headspace += md5_hash.hash_len + md5_hash.confound_len;
357 356 break;
358 357 case CRYPT_METHOD_AES128:
359 358 case CRYPT_METHOD_AES256:
360 359 headspace += DEFAULT_AES_BLOCKLEN;
361 360 break;
362 361 case CRYPT_METHOD_DES_CFB:
363 362 case CRYPT_METHOD_NONE:
364 363 break;
365 364 }
366 365
367 366 return (headspace);
368 367 }
369 368 /*
370 369 * encrypt_size
371 370 *
372 371 * Calculate the resulting size when encrypting 'plainlen' bytes
373 372 * of data.
374 373 */
375 374 static size_t
376 375 encrypt_size(struct cipher_data_t *cd, size_t plainlen)
377 376 {
378 377 size_t cipherlen;
379 378
380 379 switch (cd->method) {
381 380 case CRYPT_METHOD_DES_CBC_NULL:
382 381 cipherlen = (size_t)P2ROUNDUP(null_hash.hash_len +
383 382 plainlen, 8);
384 383 break;
385 384 case CRYPT_METHOD_DES_CBC_MD5:
386 385 cipherlen = (size_t)P2ROUNDUP(md5_hash.hash_len +
387 386 md5_hash.confound_len +
388 387 plainlen, 8);
389 388 break;
390 389 case CRYPT_METHOD_DES_CBC_CRC:
391 390 cipherlen = (size_t)P2ROUNDUP(crc32_hash.hash_len +
392 391 crc32_hash.confound_len +
393 392 plainlen, 8);
394 393 break;
395 394 case CRYPT_METHOD_DES3_CBC_SHA1:
396 395 cipherlen = (size_t)P2ROUNDUP(sha1_hash.confound_len +
397 396 plainlen, 8) +
398 397 sha1_hash.hash_len;
399 398 break;
400 399 case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
401 400 cipherlen = (size_t)P2ROUNDUP(md5_hash.confound_len +
402 401 plainlen, 1) + md5_hash.hash_len;
403 402 break;
404 403 case CRYPT_METHOD_AES128:
405 404 case CRYPT_METHOD_AES256:
406 405 /* No roundup for AES-CBC-CTS */
407 406 cipherlen = DEFAULT_AES_BLOCKLEN + plainlen +
408 407 AES_TRUNCATED_HMAC_LEN;
409 408 break;
410 409 case CRYPT_METHOD_DES_CFB:
411 410 case CRYPT_METHOD_NONE:
412 411 cipherlen = plainlen;
413 412 break;
414 413 }
415 414
416 415 return (cipherlen);
417 416 }
418 417
419 418 /*
420 419 * des_cfb_encrypt
421 420 *
422 421 * Encrypt the mblk data using DES with cipher feedback.
423 422 *
424 423 * Given that V[i] is the initial 64 bit vector, V[n] is the nth 64 bit
425 424 * vector, D[n] is the nth chunk of 64 bits of data to encrypt
426 425 * (decrypt), and O[n] is the nth chunk of 64 bits of encrypted
427 426 * (decrypted) data, then:
428 427 *
429 428 * V[0] = DES(V[i], key)
430 429 * O[n] = D[n] <exclusive or > V[n]
431 430 * V[n+1] = DES(O[n], key)
432 431 *
433 432 * The size of the message being encrypted does not change in this
434 433 * algorithm, num_bytes in == num_bytes out.
435 434 */
436 435 static mblk_t *
437 436 des_cfb_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp)
438 437 {
439 438 int savedbytes;
440 439 char *iptr, *optr, *lastoutput;
441 440
442 441 lastoutput = optr = (char *)mp->b_rptr;
443 442 iptr = (char *)mp->b_rptr;
444 443 savedbytes = tmi->enc_data.bytes % CFB_BLKSZ;
445 444
446 445 while (iptr < (char *)mp->b_wptr) {
447 446 /*
448 447 * Do DES-ECB.
449 448 * The first time this runs, the 'tmi->enc_data.block' will
450 449 * contain the initialization vector that should have been
451 450 * passed in with the SETUP ioctl.
452 451 *
453 452 * V[n] = DES(V[n-1], key)
454 453 */
455 454 if (!(tmi->enc_data.bytes % CFB_BLKSZ)) {
456 455 int retval = 0;
457 456 retval = kef_crypt(&tmi->enc_data,
458 457 tmi->enc_data.block,
459 458 CRYPTO_DATA_RAW,
460 459 tmi->enc_data.blocklen,
461 460 CRYPT_ENCRYPT);
462 461
463 462 if (retval != CRYPTO_SUCCESS) {
464 463 #ifdef DEBUG
465 464 cmn_err(CE_WARN, "des_cfb_encrypt: kef_crypt "
466 465 "failed - error 0x%0x", retval);
467 466 #endif
468 467 mp->b_datap->db_type = M_ERROR;
469 468 mp->b_rptr = mp->b_datap->db_base;
470 469 *mp->b_rptr = EIO;
471 470 mp->b_wptr = mp->b_rptr + sizeof (char);
472 471 freemsg(mp->b_cont);
473 472 mp->b_cont = NULL;
474 473 qreply(WR(q), mp);
475 474 return (NULL);
476 475 }
477 476 }
478 477
479 478 /* O[n] = I[n] ^ V[n] */
480 479 *(optr++) = *(iptr++) ^
481 480 tmi->enc_data.block[tmi->enc_data.bytes % CFB_BLKSZ];
482 481
483 482 tmi->enc_data.bytes++;
484 483 /*
485 484 * Feedback the encrypted output as the input to next DES call.
486 485 */
487 486 if (!(tmi->enc_data.bytes % CFB_BLKSZ)) {
488 487 char *dbptr = tmi->enc_data.block;
489 488 /*
490 489 * Get the last bits of input from the previous
491 490 * msg block that we haven't yet used as feedback input.
492 491 */
493 492 if (savedbytes > 0) {
494 493 bcopy(tmi->enc_data.saveblock,
495 494 dbptr, (size_t)savedbytes);
496 495 dbptr += savedbytes;
497 496 }
498 497
499 498 /*
500 499 * Now copy the correct bytes from the current input
501 500 * stream and update the 'lastoutput' ptr
502 501 */
503 502 bcopy(lastoutput, dbptr,
504 503 (size_t)(CFB_BLKSZ - savedbytes));
505 504
506 505 lastoutput += (CFB_BLKSZ - savedbytes);
507 506 savedbytes = 0;
508 507 }
509 508 }
510 509 /*
511 510 * If there are bytes of input here that we need in the next
512 511 * block to build an ivec, save them off here.
513 512 */
514 513 if (lastoutput < optr) {
515 514 bcopy(lastoutput,
516 515 tmi->enc_data.saveblock + savedbytes,
517 516 (uint_t)(optr - lastoutput));
518 517 }
519 518 return (mp);
520 519 }
521 520
522 521 /*
523 522 * des_cfb_decrypt
524 523 *
525 524 * Decrypt the data in the mblk using DES in Cipher Feedback mode
526 525 *
527 526 * # bytes in == # bytes out, no padding, confounding, or hashing
528 527 * is added.
529 528 *
530 529 */
531 530 static mblk_t *
532 531 des_cfb_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp)
533 532 {
534 533 uint_t len;
535 534 uint_t savedbytes;
536 535 char *iptr;
537 536 char *lastinput;
538 537 uint_t cp;
539 538
540 539 len = MBLKL(mp);
541 540
542 541 /* decrypted output goes into the new data buffer */
543 542 lastinput = iptr = (char *)mp->b_rptr;
544 543
545 544 savedbytes = tmi->dec_data.bytes % tmi->dec_data.blocklen;
546 545
547 546 /*
548 547 * Save the input CFB_BLKSZ bytes at a time.
549 548 * We are trying to decrypt in-place, but need to keep
550 549 * a small sliding window of encrypted text to be
551 550 * used to construct the feedback buffer.
552 551 */
553 552 cp = ((tmi->dec_data.blocklen - savedbytes) > len ? len :
554 553 tmi->dec_data.blocklen - savedbytes);
555 554
556 555 bcopy(lastinput, tmi->dec_data.saveblock + savedbytes, cp);
557 556 savedbytes += cp;
558 557
559 558 lastinput += cp;
560 559
561 560 while (iptr < (char *)mp->b_wptr) {
562 561 /*
563 562 * Do DES-ECB.
564 563 * The first time this runs, the 'tmi->dec_data.block' will
565 564 * contain the initialization vector that should have been
566 565 * passed in with the SETUP ioctl.
567 566 */
568 567 if (!(tmi->dec_data.bytes % CFB_BLKSZ)) {
569 568 int retval;
570 569 retval = kef_crypt(&tmi->dec_data,
571 570 tmi->dec_data.block,
572 571 CRYPTO_DATA_RAW,
573 572 tmi->dec_data.blocklen,
574 573 CRYPT_ENCRYPT);
575 574
576 575 if (retval != CRYPTO_SUCCESS) {
577 576 #ifdef DEBUG
578 577 cmn_err(CE_WARN, "des_cfb_decrypt: kef_crypt "
579 578 "failed - status 0x%0x", retval);
580 579 #endif
581 580 mp->b_datap->db_type = M_ERROR;
582 581 mp->b_rptr = mp->b_datap->db_base;
583 582 *mp->b_rptr = EIO;
584 583 mp->b_wptr = mp->b_rptr + sizeof (char);
585 584 freemsg(mp->b_cont);
586 585 mp->b_cont = NULL;
587 586 qreply(WR(q), mp);
588 587 return (NULL);
589 588 }
590 589 }
591 590
592 591 /*
593 592 * To decrypt, XOR the input with the output from the DES call
594 593 */
595 594 *(iptr++) ^= tmi->dec_data.block[tmi->dec_data.bytes %
596 595 CFB_BLKSZ];
597 596
598 597 tmi->dec_data.bytes++;
599 598
600 599 /*
601 600 * Feedback the encrypted input for next DES call.
602 601 */
603 602 if (!(tmi->dec_data.bytes % tmi->dec_data.blocklen)) {
604 603 char *dbptr = tmi->dec_data.block;
605 604 /*
606 605 * Get the last bits of input from the previous block
607 606 * that we haven't yet processed.
608 607 */
609 608 if (savedbytes > 0) {
610 609 bcopy(tmi->dec_data.saveblock,
611 610 dbptr, savedbytes);
612 611 dbptr += savedbytes;
613 612 }
614 613
615 614 savedbytes = 0;
616 615
617 616 /*
618 617 * This block makes sure that our local
619 618 * buffer of input data is full and can
620 619 * be accessed from the beginning.
621 620 */
622 621 if (lastinput < (char *)mp->b_wptr) {
623 622
624 623 /* How many bytes are left in the mblk? */
625 624 cp = (((char *)mp->b_wptr - lastinput) >
626 625 tmi->dec_data.blocklen ?
627 626 tmi->dec_data.blocklen :
628 627 (char *)mp->b_wptr - lastinput);
629 628
630 629 /* copy what we need */
631 630 bcopy(lastinput, tmi->dec_data.saveblock,
632 631 cp);
633 632
634 633 lastinput += cp;
635 634 savedbytes = cp;
636 635 }
637 636 }
638 637 }
639 638
640 639 return (mp);
641 640 }
642 641
643 642 /*
644 643 * crc32_calc
645 644 *
646 645 * Compute a CRC32 checksum on the input
647 646 */
648 647 static int
649 648 crc32_calc(uchar_t *buf, uchar_t *input, uint_t len)
650 649 {
651 650 uint32_t crc;
652 651
653 652 CRC32(crc, input, len, 0, crc32_table);
654 653
655 654 buf[0] = (uchar_t)(crc & 0xff);
656 655 buf[1] = (uchar_t)((crc >> 8) & 0xff);
657 656 buf[2] = (uchar_t)((crc >> 16) & 0xff);
658 657 buf[3] = (uchar_t)((crc >> 24) & 0xff);
659 658
660 659 return (CRYPTO_SUCCESS);
661 660 }
662 661
663 662 static int
664 663 kef_digest(crypto_mech_type_t digest_type,
665 664 uchar_t *input, uint_t inlen,
666 665 uchar_t *output, uint_t hashlen)
667 666 {
668 667 iovec_t v1, v2;
669 668 crypto_data_t d1, d2;
670 669 crypto_mechanism_t mech;
671 670 int rv;
672 671
673 672 mech.cm_type = digest_type;
674 673 mech.cm_param = 0;
675 674 mech.cm_param_len = 0;
676 675
677 676 v1.iov_base = (void *)input;
678 677 v1.iov_len = inlen;
679 678
680 679 d1.cd_format = CRYPTO_DATA_RAW;
681 680 d1.cd_offset = 0;
682 681 d1.cd_length = v1.iov_len;
683 682 d1.cd_raw = v1;
684 683
685 684 v2.iov_base = (void *)output;
686 685 v2.iov_len = hashlen;
687 686
688 687 d2.cd_format = CRYPTO_DATA_RAW;
689 688 d2.cd_offset = 0;
690 689 d2.cd_length = v2.iov_len;
691 690 d2.cd_raw = v2;
692 691
693 692 rv = crypto_digest(&mech, &d1, &d2, NULL);
694 693
695 694 return (rv);
696 695 }
697 696
698 697 /*
699 698 * sha1_calc
700 699 *
701 700 * Get a SHA1 hash on the input data.
702 701 */
703 702 static int
704 703 sha1_calc(uchar_t *output, uchar_t *input, uint_t inlen)
705 704 {
706 705 int rv;
707 706
708 707 rv = kef_digest(sha1_hash_mech, input, inlen, output, SHA1_HASHSIZE);
709 708
710 709 return (rv);
711 710 }
712 711
713 712 /*
714 713 * Get an MD5 hash on the input data.
715 714 * md5_calc
716 715 *
717 716 */
718 717 static int
719 718 md5_calc(uchar_t *output, uchar_t *input, uint_t inlen)
720 719 {
721 720 int rv;
722 721
723 722 rv = kef_digest(md5_hash_mech, input, inlen, output, MD5_HASHSIZE);
724 723
725 724 return (rv);
726 725 }
727 726
728 727 /*
729 728 * nfold
730 729 * duplicate the functionality of the krb5_nfold function from
731 730 * the userland kerberos mech.
732 731 * This is needed to derive keys for use with 3DES/SHA1-HMAC
733 732 * ciphers.
734 733 */
735 734 static void
736 735 nfold(int inbits, uchar_t *in, int outbits, uchar_t *out)
737 736 {
738 737 int a, b, c, lcm;
739 738 int byte, i, msbit;
740 739
741 740 inbits >>= 3;
742 741 outbits >>= 3;
743 742
744 743 /* first compute lcm(n,k) */
745 744 a = outbits;
746 745 b = inbits;
747 746
748 747 while (b != 0) {
749 748 c = b;
750 749 b = a%b;
751 750 a = c;
752 751 }
753 752
754 753 lcm = outbits*inbits/a;
755 754
756 755 /* now do the real work */
757 756
758 757 bzero(out, outbits);
759 758 byte = 0;
760 759
761 760 /*
762 761 * Compute the msbit in k which gets added into this byte
763 762 * first, start with the msbit in the first, unrotated byte
764 763 * then, for each byte, shift to the right for each repetition
765 764 * last, pick out the correct byte within that shifted repetition
766 765 */
767 766 for (i = lcm-1; i >= 0; i--) {
768 767 msbit = (((inbits<<3)-1)
769 768 +(((inbits<<3)+13)*(i/inbits))
770 769 +((inbits-(i%inbits))<<3)) %(inbits<<3);
771 770
772 771 /* pull out the byte value itself */
773 772 byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)|
774 773 (in[((inbits)-(msbit>>3))%inbits]))
775 774 >>((msbit&7)+1))&0xff;
776 775
777 776 /* do the addition */
778 777 byte += out[i%outbits];
779 778 out[i%outbits] = byte&0xff;
780 779
781 780 byte >>= 8;
782 781 }
783 782
784 783 /* if there's a carry bit left over, add it back in */
785 784 if (byte) {
786 785 for (i = outbits-1; i >= 0; i--) {
787 786 /* do the addition */
788 787 byte += out[i];
789 788 out[i] = byte&0xff;
790 789
791 790 /* keep around the carry bit, if any */
792 791 byte >>= 8;
793 792 }
794 793 }
795 794 }
796 795
797 796 #define smask(step) ((1<<step)-1)
798 797 #define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step)))
799 798 #define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1)
800 799
801 800 /*
802 801 * Duplicate the functionality of the "dk_derive_key" function
803 802 * in the Kerberos mechanism.
804 803 */
805 804 static int
806 805 derive_key(struct cipher_data_t *cdata, uchar_t *constdata,
807 806 int constlen, char *dkey, int keybytes,
808 807 int blocklen)
809 808 {
810 809 int rv = 0;
811 810 int n = 0, i;
812 811 char *inblock;
813 812 char *rawkey;
814 813 char *zeroblock;
815 814 char *saveblock;
816 815
817 816 inblock = kmem_zalloc(blocklen, KM_SLEEP);
818 817 rawkey = kmem_zalloc(keybytes, KM_SLEEP);
819 818 zeroblock = kmem_zalloc(blocklen, KM_SLEEP);
820 819
821 820 if (constlen == blocklen)
822 821 bcopy(constdata, inblock, blocklen);
823 822 else
824 823 nfold(constlen * 8, constdata,
825 824 blocklen * 8, (uchar_t *)inblock);
826 825
827 826 /*
828 827 * zeroblock is an IV of all 0's.
829 828 *
830 829 * The "block" section of the cdata record is used as the
831 830 * IV for crypto operations in the kef_crypt function.
832 831 *
833 832 * We use 'block' as a generic IV data buffer because it
834 833 * is attached to the stream state data and thus can
835 834 * be used to hold information that must carry over
836 835 * from processing of one mblk to another.
837 836 *
838 837 * Here, we save the current IV and replace it with
839 838 * and empty IV (all 0's) for use when deriving the
840 839 * keys. Once the key derivation is done, we swap the
841 840 * old IV back into place.
842 841 */
843 842 saveblock = cdata->block;
844 843 cdata->block = zeroblock;
845 844
846 845 while (n < keybytes) {
847 846 rv = kef_crypt(cdata, inblock, CRYPTO_DATA_RAW,
848 847 blocklen, CRYPT_ENCRYPT);
849 848 if (rv != CRYPTO_SUCCESS) {
850 849 /* put the original IV block back in place */
851 850 cdata->block = saveblock;
852 851 cmn_err(CE_WARN, "failed to derive a key: %0x", rv);
853 852 goto cleanup;
854 853 }
855 854
856 855 if (keybytes - n < blocklen) {
857 856 bcopy(inblock, rawkey+n, (keybytes-n));
858 857 break;
859 858 }
860 859 bcopy(inblock, rawkey+n, blocklen);
861 860 n += blocklen;
862 861 }
863 862 /* put the original IV block back in place */
864 863 cdata->block = saveblock;
865 864
866 865 /* finally, make the key */
867 866 if (cdata->method == CRYPT_METHOD_DES3_CBC_SHA1) {
868 867 /*
869 868 * 3DES key derivation requires that we make sure the
870 869 * key has the proper parity.
871 870 */
872 871 for (i = 0; i < 3; i++) {
873 872 bcopy(rawkey+(i*7), dkey+(i*8), 7);
874 873
875 874 /* 'dkey' is our derived key output buffer */
876 875 dkey[i*8+7] = (((dkey[i*8]&1)<<1) |
877 876 ((dkey[i*8+1]&1)<<2) |
878 877 ((dkey[i*8+2]&1)<<3) |
879 878 ((dkey[i*8+3]&1)<<4) |
880 879 ((dkey[i*8+4]&1)<<5) |
881 880 ((dkey[i*8+5]&1)<<6) |
882 881 ((dkey[i*8+6]&1)<<7));
883 882
884 883 for (n = 0; n < 8; n++) {
885 884 dkey[i*8 + n] &= 0xfe;
886 885 dkey[i*8 + n] |= 1^parity_char(dkey[i*8 + n]);
887 886 }
888 887 }
889 888 } else if (IS_AES_METHOD(cdata->method)) {
890 889 bcopy(rawkey, dkey, keybytes);
891 890 }
892 891 cleanup:
893 892 kmem_free(inblock, blocklen);
894 893 kmem_free(zeroblock, blocklen);
895 894 kmem_free(rawkey, keybytes);
896 895 return (rv);
897 896 }
898 897
899 898 /*
900 899 * create_derived_keys
901 900 *
902 901 * Algorithm for deriving a new key and an HMAC key
903 902 * before computing the 3DES-SHA1-HMAC operation on the plaintext
904 903 * This algorithm matches the work done by Kerberos mechanism
905 904 * in userland.
906 905 */
907 906 static int
908 907 create_derived_keys(struct cipher_data_t *cdata, uint32_t usage,
909 908 crypto_key_t *enckey, crypto_key_t *hmackey)
910 909 {
911 910 uchar_t constdata[K5CLENGTH];
912 911 int keybytes;
913 912 int rv;
914 913
915 914 constdata[0] = (usage>>24)&0xff;
916 915 constdata[1] = (usage>>16)&0xff;
917 916 constdata[2] = (usage>>8)&0xff;
918 917 constdata[3] = usage & 0xff;
919 918 /* Use "0xAA" for deriving encryption key */
920 919 constdata[4] = 0xAA; /* from MIT Kerberos code */
921 920
922 921 enckey->ck_length = cdata->keylen * 8;
923 922 enckey->ck_format = CRYPTO_KEY_RAW;
924 923 enckey->ck_data = kmem_zalloc(cdata->keylen, KM_SLEEP);
925 924
926 925 switch (cdata->method) {
927 926 case CRYPT_METHOD_DES_CFB:
928 927 case CRYPT_METHOD_DES_CBC_NULL:
929 928 case CRYPT_METHOD_DES_CBC_MD5:
930 929 case CRYPT_METHOD_DES_CBC_CRC:
931 930 keybytes = 8;
932 931 break;
933 932 case CRYPT_METHOD_DES3_CBC_SHA1:
934 933 keybytes = CRYPT_DES3_KEYBYTES;
935 934 break;
936 935 case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
937 936 case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP:
938 937 keybytes = CRYPT_ARCFOUR_KEYBYTES;
939 938 break;
940 939 case CRYPT_METHOD_AES128:
941 940 keybytes = CRYPT_AES128_KEYBYTES;
942 941 break;
943 942 case CRYPT_METHOD_AES256:
944 943 keybytes = CRYPT_AES256_KEYBYTES;
945 944 break;
946 945 }
947 946
948 947 /* derive main crypto key */
949 948 rv = derive_key(cdata, constdata, sizeof (constdata),
950 949 enckey->ck_data, keybytes, cdata->blocklen);
951 950
952 951 if (rv == CRYPTO_SUCCESS) {
953 952
954 953 /* Use "0x55" for deriving mac key */
955 954 constdata[4] = 0x55;
956 955
957 956 hmackey->ck_length = cdata->keylen * 8;
958 957 hmackey->ck_format = CRYPTO_KEY_RAW;
959 958 hmackey->ck_data = kmem_zalloc(cdata->keylen, KM_SLEEP);
960 959
961 960 rv = derive_key(cdata, constdata, sizeof (constdata),
962 961 hmackey->ck_data, keybytes,
963 962 cdata->blocklen);
964 963 } else {
965 964 cmn_err(CE_WARN, "failed to derive crypto key: %02x", rv);
966 965 }
967 966
968 967 return (rv);
969 968 }
970 969
971 970 /*
972 971 * Compute 3-DES crypto and HMAC.
973 972 */
974 973 static int
975 974 kef_decr_hmac(struct cipher_data_t *cdata,
976 975 mblk_t *mp, int length,
977 976 char *hmac, int hmaclen)
978 977 {
979 978 int rv = CRYPTO_FAILED;
980 979
981 980 crypto_mechanism_t encr_mech;
982 981 crypto_mechanism_t mac_mech;
983 982 crypto_data_t dd;
984 983 crypto_data_t mac;
985 984 iovec_t v1;
986 985
987 986 ASSERT(cdata != NULL);
988 987 ASSERT(mp != NULL);
989 988 ASSERT(hmac != NULL);
990 989
991 990 bzero(&dd, sizeof (dd));
992 991 dd.cd_format = CRYPTO_DATA_MBLK;
993 992 dd.cd_offset = 0;
994 993 dd.cd_length = length;
995 994 dd.cd_mp = mp;
996 995
997 996 v1.iov_base = hmac;
998 997 v1.iov_len = hmaclen;
999 998
1000 999 mac.cd_format = CRYPTO_DATA_RAW;
1001 1000 mac.cd_offset = 0;
1002 1001 mac.cd_length = hmaclen;
1003 1002 mac.cd_raw = v1;
1004 1003
1005 1004 /*
1006 1005 * cdata->block holds the IVEC
1007 1006 */
1008 1007 encr_mech.cm_type = cdata->mech_type;
1009 1008 encr_mech.cm_param = cdata->block;
1010 1009
1011 1010 if (cdata->block != NULL)
1012 1011 encr_mech.cm_param_len = cdata->blocklen;
1013 1012 else
1014 1013 encr_mech.cm_param_len = 0;
1015 1014
1016 1015 rv = crypto_decrypt(&encr_mech, &dd, &cdata->d_encr_key,
1017 1016 cdata->enc_tmpl, NULL, NULL);
1018 1017 if (rv != CRYPTO_SUCCESS) {
1019 1018 cmn_err(CE_WARN, "crypto_decrypt failed: %0x", rv);
1020 1019 return (rv);
1021 1020 }
1022 1021
1023 1022 mac_mech.cm_type = sha1_hmac_mech;
1024 1023 mac_mech.cm_param = NULL;
1025 1024 mac_mech.cm_param_len = 0;
1026 1025
1027 1026 /*
1028 1027 * Compute MAC of the plaintext decrypted above.
1029 1028 */
1030 1029 rv = crypto_mac(&mac_mech, &dd, &cdata->d_hmac_key,
1031 1030 cdata->hmac_tmpl, &mac, NULL);
1032 1031
1033 1032 if (rv != CRYPTO_SUCCESS) {
1034 1033 cmn_err(CE_WARN, "crypto_mac failed: %0x", rv);
1035 1034 }
1036 1035
1037 1036 return (rv);
1038 1037 }
1039 1038
1040 1039 /*
1041 1040 * Compute 3-DES crypto and HMAC.
1042 1041 */
1043 1042 static int
1044 1043 kef_encr_hmac(struct cipher_data_t *cdata,
1045 1044 mblk_t *mp, int length,
1046 1045 char *hmac, int hmaclen)
1047 1046 {
1048 1047 int rv = CRYPTO_FAILED;
1049 1048
1050 1049 crypto_mechanism_t encr_mech;
1051 1050 crypto_mechanism_t mac_mech;
1052 1051 crypto_data_t dd;
1053 1052 crypto_data_t mac;
1054 1053 iovec_t v1;
1055 1054
1056 1055 ASSERT(cdata != NULL);
1057 1056 ASSERT(mp != NULL);
1058 1057 ASSERT(hmac != NULL);
1059 1058
1060 1059 bzero(&dd, sizeof (dd));
1061 1060 dd.cd_format = CRYPTO_DATA_MBLK;
1062 1061 dd.cd_offset = 0;
1063 1062 dd.cd_length = length;
1064 1063 dd.cd_mp = mp;
1065 1064
1066 1065 v1.iov_base = hmac;
1067 1066 v1.iov_len = hmaclen;
1068 1067
1069 1068 mac.cd_format = CRYPTO_DATA_RAW;
1070 1069 mac.cd_offset = 0;
1071 1070 mac.cd_length = hmaclen;
1072 1071 mac.cd_raw = v1;
1073 1072
1074 1073 /*
1075 1074 * cdata->block holds the IVEC
1076 1075 */
1077 1076 encr_mech.cm_type = cdata->mech_type;
1078 1077 encr_mech.cm_param = cdata->block;
1079 1078
1080 1079 if (cdata->block != NULL)
1081 1080 encr_mech.cm_param_len = cdata->blocklen;
1082 1081 else
1083 1082 encr_mech.cm_param_len = 0;
1084 1083
1085 1084 mac_mech.cm_type = sha1_hmac_mech;
1086 1085 mac_mech.cm_param = NULL;
1087 1086 mac_mech.cm_param_len = 0;
1088 1087
1089 1088 rv = crypto_mac(&mac_mech, &dd, &cdata->d_hmac_key,
1090 1089 cdata->hmac_tmpl, &mac, NULL);
1091 1090
1092 1091 if (rv != CRYPTO_SUCCESS) {
1093 1092 cmn_err(CE_WARN, "crypto_mac failed: %0x", rv);
1094 1093 return (rv);
1095 1094 }
1096 1095
1097 1096 rv = crypto_encrypt(&encr_mech, &dd, &cdata->d_encr_key,
1098 1097 cdata->enc_tmpl, NULL, NULL);
1099 1098 if (rv != CRYPTO_SUCCESS) {
1100 1099 cmn_err(CE_WARN, "crypto_encrypt failed: %0x", rv);
1101 1100 }
1102 1101
1103 1102 return (rv);
1104 1103 }
1105 1104
1106 1105 /*
1107 1106 * kef_crypt
1108 1107 *
1109 1108 * Use the Kernel encryption framework to provide the
1110 1109 * crypto operations for the indicated data.
1111 1110 */
1112 1111 static int
1113 1112 kef_crypt(struct cipher_data_t *cdata,
1114 1113 void *indata, crypto_data_format_t fmt,
1115 1114 size_t length, int mode)
1116 1115 {
1117 1116 int rv = CRYPTO_FAILED;
1118 1117
1119 1118 crypto_mechanism_t mech;
1120 1119 crypto_key_t crkey;
1121 1120 iovec_t v1;
1122 1121 crypto_data_t d1;
1123 1122
1124 1123 ASSERT(cdata != NULL);
1125 1124 ASSERT(indata != NULL);
1126 1125 ASSERT(fmt == CRYPTO_DATA_RAW || fmt == CRYPTO_DATA_MBLK);
1127 1126
1128 1127 bzero(&crkey, sizeof (crkey));
1129 1128 bzero(&d1, sizeof (d1));
1130 1129
1131 1130 crkey.ck_format = CRYPTO_KEY_RAW;
1132 1131 crkey.ck_data = cdata->key;
1133 1132
1134 1133 /* keys are measured in bits, not bytes, so multiply by 8 */
1135 1134 crkey.ck_length = cdata->keylen * 8;
1136 1135
1137 1136 if (fmt == CRYPTO_DATA_RAW) {
1138 1137 v1.iov_base = (char *)indata;
1139 1138 v1.iov_len = length;
1140 1139 }
1141 1140
1142 1141 d1.cd_format = fmt;
1143 1142 d1.cd_offset = 0;
1144 1143 d1.cd_length = length;
1145 1144 if (fmt == CRYPTO_DATA_RAW)
1146 1145 d1.cd_raw = v1;
1147 1146 else if (fmt == CRYPTO_DATA_MBLK)
1148 1147 d1.cd_mp = (mblk_t *)indata;
1149 1148
1150 1149 mech.cm_type = cdata->mech_type;
1151 1150 mech.cm_param = cdata->block;
1152 1151 /*
1153 1152 * cdata->block holds the IVEC
1154 1153 */
1155 1154 if (cdata->block != NULL)
1156 1155 mech.cm_param_len = cdata->blocklen;
1157 1156 else
1158 1157 mech.cm_param_len = 0;
1159 1158
1160 1159 /*
1161 1160 * encrypt and decrypt in-place
1162 1161 */
1163 1162 if (mode == CRYPT_ENCRYPT)
1164 1163 rv = crypto_encrypt(&mech, &d1, &crkey, NULL, NULL, NULL);
1165 1164 else
1166 1165 rv = crypto_decrypt(&mech, &d1, &crkey, NULL, NULL, NULL);
1167 1166
1168 1167 if (rv != CRYPTO_SUCCESS) {
1169 1168 cmn_err(CE_WARN, "%s returned error %08x",
1170 1169 (mode == CRYPT_ENCRYPT ? "crypto_encrypt" :
1171 1170 "crypto_decrypt"), rv);
1172 1171 return (CRYPTO_FAILED);
1173 1172 }
1174 1173
1175 1174 return (rv);
1176 1175 }
1177 1176
1178 1177 static int
1179 1178 do_hmac(crypto_mech_type_t mech,
1180 1179 crypto_key_t *key,
1181 1180 char *data, int datalen,
1182 1181 char *hmac, int hmaclen)
1183 1182 {
1184 1183 int rv = 0;
1185 1184 crypto_mechanism_t mac_mech;
1186 1185 crypto_data_t dd;
1187 1186 crypto_data_t mac;
1188 1187 iovec_t vdata, vmac;
1189 1188
1190 1189 mac_mech.cm_type = mech;
1191 1190 mac_mech.cm_param = NULL;
1192 1191 mac_mech.cm_param_len = 0;
1193 1192
1194 1193 vdata.iov_base = data;
1195 1194 vdata.iov_len = datalen;
1196 1195
1197 1196 bzero(&dd, sizeof (dd));
1198 1197 dd.cd_format = CRYPTO_DATA_RAW;
1199 1198 dd.cd_offset = 0;
1200 1199 dd.cd_length = datalen;
1201 1200 dd.cd_raw = vdata;
1202 1201
1203 1202 vmac.iov_base = hmac;
1204 1203 vmac.iov_len = hmaclen;
1205 1204
1206 1205 mac.cd_format = CRYPTO_DATA_RAW;
1207 1206 mac.cd_offset = 0;
1208 1207 mac.cd_length = hmaclen;
1209 1208 mac.cd_raw = vmac;
1210 1209
1211 1210 /*
1212 1211 * Compute MAC of the plaintext decrypted above.
1213 1212 */
1214 1213 rv = crypto_mac(&mac_mech, &dd, key, NULL, &mac, NULL);
1215 1214
1216 1215 if (rv != CRYPTO_SUCCESS) {
1217 1216 cmn_err(CE_WARN, "crypto_mac failed: %0x", rv);
1218 1217 }
1219 1218
1220 1219 return (rv);
1221 1220 }
1222 1221
1223 1222 #define XOR_BLOCK(src, dst) \
1224 1223 (dst)[0] ^= (src)[0]; \
1225 1224 (dst)[1] ^= (src)[1]; \
1226 1225 (dst)[2] ^= (src)[2]; \
1227 1226 (dst)[3] ^= (src)[3]; \
1228 1227 (dst)[4] ^= (src)[4]; \
1229 1228 (dst)[5] ^= (src)[5]; \
1230 1229 (dst)[6] ^= (src)[6]; \
1231 1230 (dst)[7] ^= (src)[7]; \
1232 1231 (dst)[8] ^= (src)[8]; \
1233 1232 (dst)[9] ^= (src)[9]; \
1234 1233 (dst)[10] ^= (src)[10]; \
1235 1234 (dst)[11] ^= (src)[11]; \
1236 1235 (dst)[12] ^= (src)[12]; \
1237 1236 (dst)[13] ^= (src)[13]; \
1238 1237 (dst)[14] ^= (src)[14]; \
1239 1238 (dst)[15] ^= (src)[15]
1240 1239
1241 1240 #define xorblock(x, y) XOR_BLOCK(y, x)
1242 1241
1243 1242 static int
1244 1243 aes_cbc_cts_encrypt(struct tmodinfo *tmi, uchar_t *plain, size_t length)
1245 1244 {
1246 1245 int result = CRYPTO_SUCCESS;
1247 1246 unsigned char tmp[DEFAULT_AES_BLOCKLEN];
1248 1247 unsigned char tmp2[DEFAULT_AES_BLOCKLEN];
1249 1248 unsigned char tmp3[DEFAULT_AES_BLOCKLEN];
1250 1249 int nblocks = 0, blockno;
1251 1250 crypto_data_t ct, pt;
1252 1251 crypto_mechanism_t mech;
1253 1252
1254 1253 mech.cm_type = tmi->enc_data.mech_type;
1255 1254 if (tmi->enc_data.ivlen > 0 && tmi->enc_data.ivec != NULL) {
1256 1255 bcopy(tmi->enc_data.ivec, tmp, DEFAULT_AES_BLOCKLEN);
1257 1256 } else {
1258 1257 bzero(tmp, sizeof (tmp));
1259 1258 }
1260 1259 mech.cm_param = NULL;
1261 1260 mech.cm_param_len = 0;
1262 1261
1263 1262 nblocks = (length + DEFAULT_AES_BLOCKLEN - 1) / DEFAULT_AES_BLOCKLEN;
1264 1263
1265 1264 bzero(&ct, sizeof (crypto_data_t));
1266 1265 bzero(&pt, sizeof (crypto_data_t));
1267 1266
1268 1267 if (nblocks == 1) {
1269 1268 pt.cd_format = CRYPTO_DATA_RAW;
1270 1269 pt.cd_length = length;
1271 1270 pt.cd_raw.iov_base = (char *)plain;
1272 1271 pt.cd_raw.iov_len = length;
1273 1272
1274 1273 result = crypto_encrypt(&mech, &pt,
1275 1274 &tmi->enc_data.d_encr_key, NULL, NULL, NULL);
1276 1275
1277 1276 if (result != CRYPTO_SUCCESS) {
1278 1277 cmn_err(CE_WARN, "aes_cbc_cts_encrypt: "
1279 1278 "crypto_encrypt failed: %0x", result);
1280 1279 }
1281 1280 } else {
1282 1281 size_t nleft;
1283 1282
1284 1283 ct.cd_format = CRYPTO_DATA_RAW;
1285 1284 ct.cd_offset = 0;
1286 1285 ct.cd_length = DEFAULT_AES_BLOCKLEN;
1287 1286
1288 1287 pt.cd_format = CRYPTO_DATA_RAW;
1289 1288 pt.cd_offset = 0;
1290 1289 pt.cd_length = DEFAULT_AES_BLOCKLEN;
1291 1290
1292 1291 result = crypto_encrypt_init(&mech,
1293 1292 &tmi->enc_data.d_encr_key,
1294 1293 tmi->enc_data.enc_tmpl,
1295 1294 &tmi->enc_data.ctx, NULL);
1296 1295
1297 1296 if (result != CRYPTO_SUCCESS) {
1298 1297 cmn_err(CE_WARN, "aes_cbc_cts_encrypt: "
1299 1298 "crypto_encrypt_init failed: %0x", result);
1300 1299 goto cleanup;
1301 1300 }
1302 1301
1303 1302 for (blockno = 0; blockno < nblocks - 2; blockno++) {
1304 1303 xorblock(tmp, plain + blockno * DEFAULT_AES_BLOCKLEN);
1305 1304
1306 1305 pt.cd_raw.iov_base = (char *)tmp;
1307 1306 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1308 1307
1309 1308 ct.cd_raw.iov_base = (char *)plain +
1310 1309 blockno * DEFAULT_AES_BLOCKLEN;
1311 1310 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1312 1311
1313 1312 result = crypto_encrypt_update(tmi->enc_data.ctx,
1314 1313 &pt, &ct, NULL);
1315 1314
1316 1315 if (result != CRYPTO_SUCCESS) {
1317 1316 cmn_err(CE_WARN, "aes_cbc_cts_encrypt: "
1318 1317 "crypto_encrypt_update failed: %0x",
1319 1318 result);
1320 1319 goto cleanup;
1321 1320 }
1322 1321 /* copy result over original bytes */
1323 1322 /* make another copy for the next XOR step */
1324 1323 bcopy(plain + blockno * DEFAULT_AES_BLOCKLEN,
1325 1324 tmp, DEFAULT_AES_BLOCKLEN);
1326 1325 }
1327 1326 /* XOR cipher text from n-3 with plain text from n-2 */
1328 1327 xorblock(tmp, plain + (nblocks - 2) * DEFAULT_AES_BLOCKLEN);
1329 1328
1330 1329 pt.cd_raw.iov_base = (char *)tmp;
1331 1330 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1332 1331
1333 1332 ct.cd_raw.iov_base = (char *)tmp2;
1334 1333 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1335 1334
1336 1335 /* encrypt XOR-ed block N-2 */
1337 1336 result = crypto_encrypt_update(tmi->enc_data.ctx,
1338 1337 &pt, &ct, NULL);
1339 1338 if (result != CRYPTO_SUCCESS) {
1340 1339 cmn_err(CE_WARN, "aes_cbc_cts_encrypt: "
1341 1340 "crypto_encrypt_update(2) failed: %0x",
1342 1341 result);
1343 1342 goto cleanup;
1344 1343 }
1345 1344 nleft = length - (nblocks - 1) * DEFAULT_AES_BLOCKLEN;
1346 1345
1347 1346 bzero(tmp3, sizeof (tmp3));
1348 1347 /* Save final plaintext bytes from n-1 */
1349 1348 bcopy(plain + (nblocks - 1) * DEFAULT_AES_BLOCKLEN, tmp3,
1350 1349 nleft);
1351 1350
1352 1351 /* Overwrite n-1 with cipher text from n-2 */
1353 1352 bcopy(tmp2, plain + (nblocks - 1) * DEFAULT_AES_BLOCKLEN,
1354 1353 nleft);
1355 1354
1356 1355 bcopy(tmp2, tmp, DEFAULT_AES_BLOCKLEN);
1357 1356 /* XOR cipher text from n-1 with plain text from n-1 */
1358 1357 xorblock(tmp, tmp3);
1359 1358
1360 1359 pt.cd_raw.iov_base = (char *)tmp;
1361 1360 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1362 1361
1363 1362 ct.cd_raw.iov_base = (char *)tmp2;
1364 1363 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1365 1364
1366 1365 /* encrypt block N-2 */
1367 1366 result = crypto_encrypt_update(tmi->enc_data.ctx,
1368 1367 &pt, &ct, NULL);
1369 1368
1370 1369 if (result != CRYPTO_SUCCESS) {
1371 1370 cmn_err(CE_WARN, "aes_cbc_cts_encrypt: "
1372 1371 "crypto_encrypt_update(3) failed: %0x",
1373 1372 result);
1374 1373 goto cleanup;
1375 1374 }
1376 1375
1377 1376 bcopy(tmp2, plain + (nblocks - 2) * DEFAULT_AES_BLOCKLEN,
1378 1377 DEFAULT_AES_BLOCKLEN);
1379 1378
1380 1379
1381 1380 ct.cd_raw.iov_base = (char *)tmp2;
1382 1381 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1383 1382
1384 1383 /*
1385 1384 * Ignore the output on the final step.
1386 1385 */
1387 1386 result = crypto_encrypt_final(tmi->enc_data.ctx, &ct, NULL);
1388 1387 if (result != CRYPTO_SUCCESS) {
1389 1388 cmn_err(CE_WARN, "aes_cbc_cts_encrypt: "
1390 1389 "crypto_encrypt_final(3) failed: %0x",
1391 1390 result);
1392 1391 }
1393 1392 tmi->enc_data.ctx = NULL;
1394 1393 }
1395 1394 cleanup:
1396 1395 bzero(tmp, sizeof (tmp));
1397 1396 bzero(tmp2, sizeof (tmp));
1398 1397 bzero(tmp3, sizeof (tmp));
1399 1398 bzero(tmi->enc_data.block, tmi->enc_data.blocklen);
1400 1399 return (result);
1401 1400 }
1402 1401
1403 1402 static int
1404 1403 aes_cbc_cts_decrypt(struct tmodinfo *tmi, uchar_t *buff, size_t length)
1405 1404 {
1406 1405 int result = CRYPTO_SUCCESS;
1407 1406 unsigned char tmp[DEFAULT_AES_BLOCKLEN];
1408 1407 unsigned char tmp2[DEFAULT_AES_BLOCKLEN];
1409 1408 unsigned char tmp3[DEFAULT_AES_BLOCKLEN];
1410 1409 int nblocks = 0, blockno;
1411 1410 crypto_data_t ct, pt;
1412 1411 crypto_mechanism_t mech;
1413 1412
1414 1413 mech.cm_type = tmi->enc_data.mech_type;
1415 1414
1416 1415 if (tmi->dec_data.ivec_usage != IVEC_NEVER &&
1417 1416 tmi->dec_data.ivlen > 0 && tmi->dec_data.ivec != NULL) {
1418 1417 bcopy(tmi->dec_data.ivec, tmp, DEFAULT_AES_BLOCKLEN);
1419 1418 } else {
1420 1419 bzero(tmp, sizeof (tmp));
1421 1420 }
1422 1421 mech.cm_param_len = 0;
1423 1422 mech.cm_param = NULL;
1424 1423
1425 1424 nblocks = (length + DEFAULT_AES_BLOCKLEN - 1) / DEFAULT_AES_BLOCKLEN;
1426 1425
1427 1426 bzero(&pt, sizeof (pt));
1428 1427 bzero(&ct, sizeof (ct));
1429 1428
1430 1429 if (nblocks == 1) {
1431 1430 ct.cd_format = CRYPTO_DATA_RAW;
1432 1431 ct.cd_length = length;
1433 1432 ct.cd_raw.iov_base = (char *)buff;
1434 1433 ct.cd_raw.iov_len = length;
1435 1434
1436 1435 result = crypto_decrypt(&mech, &ct,
1437 1436 &tmi->dec_data.d_encr_key, NULL, NULL, NULL);
1438 1437
1439 1438 if (result != CRYPTO_SUCCESS) {
1440 1439 cmn_err(CE_WARN, "aes_cbc_cts_decrypt: "
1441 1440 "crypto_decrypt failed: %0x", result);
1442 1441 goto cleanup;
1443 1442 }
1444 1443 } else {
1445 1444 ct.cd_format = CRYPTO_DATA_RAW;
1446 1445 ct.cd_offset = 0;
1447 1446 ct.cd_length = DEFAULT_AES_BLOCKLEN;
1448 1447
1449 1448 pt.cd_format = CRYPTO_DATA_RAW;
1450 1449 pt.cd_offset = 0;
1451 1450 pt.cd_length = DEFAULT_AES_BLOCKLEN;
1452 1451
1453 1452 result = crypto_decrypt_init(&mech,
1454 1453 &tmi->dec_data.d_encr_key,
1455 1454 tmi->dec_data.enc_tmpl,
1456 1455 &tmi->dec_data.ctx, NULL);
1457 1456
1458 1457 if (result != CRYPTO_SUCCESS) {
1459 1458 cmn_err(CE_WARN, "aes_cbc_cts_decrypt: "
1460 1459 "crypto_decrypt_init failed: %0x", result);
1461 1460 goto cleanup;
1462 1461 }
1463 1462 for (blockno = 0; blockno < nblocks - 2; blockno++) {
1464 1463 ct.cd_raw.iov_base = (char *)buff +
1465 1464 (blockno * DEFAULT_AES_BLOCKLEN);
1466 1465 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1467 1466
1468 1467 pt.cd_raw.iov_base = (char *)tmp2;
1469 1468 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1470 1469
1471 1470 /*
1472 1471 * Save the input to the decrypt so it can
1473 1472 * be used later for an XOR operation
1474 1473 */
1475 1474 bcopy(buff + (blockno * DEFAULT_AES_BLOCKLEN),
1476 1475 tmi->dec_data.block, DEFAULT_AES_BLOCKLEN);
1477 1476
1478 1477 result = crypto_decrypt_update(tmi->dec_data.ctx,
1479 1478 &ct, &pt, NULL);
1480 1479 if (result != CRYPTO_SUCCESS) {
1481 1480 cmn_err(CE_WARN, "aes_cbc_cts_decrypt: "
1482 1481 "crypto_decrypt_update(1) error - "
1483 1482 "result = 0x%08x", result);
1484 1483 goto cleanup;
1485 1484 }
1486 1485 xorblock(tmp2, tmp);
1487 1486 bcopy(tmp2, buff + blockno * DEFAULT_AES_BLOCKLEN,
1488 1487 DEFAULT_AES_BLOCKLEN);
1489 1488 /*
1490 1489 * The original cipher text is used as the xor
1491 1490 * for the next block, save it here.
1492 1491 */
1493 1492 bcopy(tmi->dec_data.block, tmp, DEFAULT_AES_BLOCKLEN);
1494 1493 }
1495 1494 ct.cd_raw.iov_base = (char *)buff +
1496 1495 ((nblocks - 2) * DEFAULT_AES_BLOCKLEN);
1497 1496 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1498 1497 pt.cd_raw.iov_base = (char *)tmp2;
1499 1498 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1500 1499
1501 1500 result = crypto_decrypt_update(tmi->dec_data.ctx,
1502 1501 &ct, &pt, NULL);
1503 1502 if (result != CRYPTO_SUCCESS) {
1504 1503 cmn_err(CE_WARN,
1505 1504 "aes_cbc_cts_decrypt: "
1506 1505 "crypto_decrypt_update(2) error -"
1507 1506 " result = 0x%08x", result);
1508 1507 goto cleanup;
1509 1508 }
1510 1509 bzero(tmp3, sizeof (tmp3));
1511 1510 bcopy(buff + (nblocks - 1) * DEFAULT_AES_BLOCKLEN, tmp3,
1512 1511 length - ((nblocks - 1) * DEFAULT_AES_BLOCKLEN));
1513 1512
1514 1513 xorblock(tmp2, tmp3);
1515 1514 bcopy(tmp2, buff + (nblocks - 1) * DEFAULT_AES_BLOCKLEN,
1516 1515 length - ((nblocks - 1) * DEFAULT_AES_BLOCKLEN));
1517 1516
1518 1517 /* 2nd to last block ... */
1519 1518 bcopy(tmp3, tmp2,
1520 1519 length - ((nblocks - 1) * DEFAULT_AES_BLOCKLEN));
1521 1520
1522 1521 ct.cd_raw.iov_base = (char *)tmp2;
1523 1522 ct.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1524 1523 pt.cd_raw.iov_base = (char *)tmp3;
1525 1524 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1526 1525
1527 1526 result = crypto_decrypt_update(tmi->dec_data.ctx,
1528 1527 &ct, &pt, NULL);
1529 1528 if (result != CRYPTO_SUCCESS) {
1530 1529 cmn_err(CE_WARN,
1531 1530 "aes_cbc_cts_decrypt: "
1532 1531 "crypto_decrypt_update(3) error - "
1533 1532 "result = 0x%08x", result);
1534 1533 goto cleanup;
1535 1534 }
1536 1535 xorblock(tmp3, tmp);
1537 1536
1538 1537
1539 1538 /* Finally, update the 2nd to last block and we are done. */
1540 1539 bcopy(tmp3, buff + (nblocks - 2) * DEFAULT_AES_BLOCKLEN,
1541 1540 DEFAULT_AES_BLOCKLEN);
1542 1541
1543 1542 /* Do Final step, but ignore output */
1544 1543 pt.cd_raw.iov_base = (char *)tmp2;
1545 1544 pt.cd_raw.iov_len = DEFAULT_AES_BLOCKLEN;
1546 1545 result = crypto_decrypt_final(tmi->dec_data.ctx, &pt, NULL);
1547 1546 if (result != CRYPTO_SUCCESS) {
1548 1547 cmn_err(CE_WARN, "aes_cbc_cts_decrypt: "
1549 1548 "crypto_decrypt_final error - "
1550 1549 "result = 0x%0x", result);
1551 1550 }
1552 1551 tmi->dec_data.ctx = NULL;
1553 1552 }
1554 1553
1555 1554 cleanup:
1556 1555 bzero(tmp, sizeof (tmp));
1557 1556 bzero(tmp2, sizeof (tmp));
1558 1557 bzero(tmp3, sizeof (tmp));
1559 1558 bzero(tmi->dec_data.block, tmi->dec_data.blocklen);
1560 1559 return (result);
1561 1560 }
1562 1561
1563 1562 /*
1564 1563 * AES decrypt
1565 1564 *
1566 1565 * format of ciphertext when using AES
1567 1566 * +-------------+------------+------------+
1568 1567 * | confounder | msg-data | hmac |
1569 1568 * +-------------+------------+------------+
1570 1569 */
1571 1570 static mblk_t *
1572 1571 aes_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp,
1573 1572 hash_info_t *hash)
1574 1573 {
1575 1574 int result;
1576 1575 size_t enclen;
1577 1576 size_t inlen;
1578 1577 uchar_t hmacbuff[64];
1579 1578 uchar_t tmpiv[DEFAULT_AES_BLOCKLEN];
1580 1579
1581 1580 inlen = (size_t)MBLKL(mp);
1582 1581
1583 1582 enclen = inlen - AES_TRUNCATED_HMAC_LEN;
1584 1583 if (tmi->dec_data.ivec_usage != IVEC_NEVER &&
1585 1584 tmi->dec_data.ivec != NULL && tmi->dec_data.ivlen > 0) {
1586 1585 int nblocks = (enclen + DEFAULT_AES_BLOCKLEN - 1) /
1587 1586 DEFAULT_AES_BLOCKLEN;
1588 1587 bcopy(mp->b_rptr + DEFAULT_AES_BLOCKLEN * (nblocks - 2),
1589 1588 tmpiv, DEFAULT_AES_BLOCKLEN);
1590 1589 }
1591 1590
1592 1591 /* AES Decrypt */
1593 1592 result = aes_cbc_cts_decrypt(tmi, mp->b_rptr, enclen);
1594 1593
1595 1594 if (result != CRYPTO_SUCCESS) {
1596 1595 cmn_err(CE_WARN,
1597 1596 "aes_decrypt: aes_cbc_cts_decrypt "
1598 1597 "failed - error %0x", result);
1599 1598 goto cleanup;
1600 1599 }
1601 1600
1602 1601 /* Verify the HMAC */
1603 1602 result = do_hmac(sha1_hmac_mech,
1604 1603 &tmi->dec_data.d_hmac_key,
1605 1604 (char *)mp->b_rptr, enclen,
1606 1605 (char *)hmacbuff, hash->hash_len);
1607 1606
1608 1607 if (result != CRYPTO_SUCCESS) {
1609 1608 cmn_err(CE_WARN,
1610 1609 "aes_decrypt: do_hmac failed - error %0x", result);
1611 1610 goto cleanup;
1612 1611 }
1613 1612
1614 1613 if (bcmp(hmacbuff, mp->b_rptr + enclen,
1615 1614 AES_TRUNCATED_HMAC_LEN) != 0) {
1616 1615 result = -1;
1617 1616 cmn_err(CE_WARN, "aes_decrypt: checksum verification failed");
1618 1617 goto cleanup;
1619 1618 }
1620 1619
1621 1620 /* truncate the mblk at the end of the decrypted text */
1622 1621 mp->b_wptr = mp->b_rptr + enclen;
1623 1622
1624 1623 /* Adjust the beginning of the buffer to skip the confounder */
1625 1624 mp->b_rptr += DEFAULT_AES_BLOCKLEN;
1626 1625
1627 1626 if (tmi->dec_data.ivec_usage != IVEC_NEVER &&
1628 1627 tmi->dec_data.ivec != NULL && tmi->dec_data.ivlen > 0)
1629 1628 bcopy(tmpiv, tmi->dec_data.ivec, DEFAULT_AES_BLOCKLEN);
1630 1629
1631 1630 cleanup:
1632 1631 if (result != CRYPTO_SUCCESS) {
1633 1632 mp->b_datap->db_type = M_ERROR;
1634 1633 mp->b_rptr = mp->b_datap->db_base;
1635 1634 *mp->b_rptr = EIO;
1636 1635 mp->b_wptr = mp->b_rptr + sizeof (char);
1637 1636 freemsg(mp->b_cont);
1638 1637 mp->b_cont = NULL;
1639 1638 qreply(WR(q), mp);
1640 1639 return (NULL);
1641 1640 }
1642 1641 return (mp);
1643 1642 }
1644 1643
1645 1644 /*
1646 1645 * AES encrypt
1647 1646 *
1648 1647 * format of ciphertext when using AES
1649 1648 * +-------------+------------+------------+
1650 1649 * | confounder | msg-data | hmac |
1651 1650 * +-------------+------------+------------+
1652 1651 */
1653 1652 static mblk_t *
1654 1653 aes_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp,
1655 1654 hash_info_t *hash)
1656 1655 {
1657 1656 int result;
1658 1657 size_t cipherlen;
1659 1658 size_t inlen;
1660 1659 uchar_t hmacbuff[64];
1661 1660
1662 1661 inlen = (size_t)MBLKL(mp);
1663 1662
1664 1663 cipherlen = encrypt_size(&tmi->enc_data, inlen);
1665 1664
1666 1665 ASSERT(MBLKSIZE(mp) >= cipherlen);
1667 1666
1668 1667 /*
1669 1668 * Shift the rptr back enough to insert the confounder.
1670 1669 */
1671 1670 mp->b_rptr -= DEFAULT_AES_BLOCKLEN;
1672 1671
1673 1672 /* Get random data for confounder */
1674 1673 (void) random_get_pseudo_bytes((uint8_t *)mp->b_rptr,
1675 1674 DEFAULT_AES_BLOCKLEN);
1676 1675
1677 1676 /*
1678 1677 * Because we encrypt in-place, we need to calculate
1679 1678 * the HMAC of the plaintext now, then stick it on
1680 1679 * the end of the ciphertext down below.
1681 1680 */
1682 1681 result = do_hmac(sha1_hmac_mech,
1683 1682 &tmi->enc_data.d_hmac_key,
1684 1683 (char *)mp->b_rptr, DEFAULT_AES_BLOCKLEN + inlen,
1685 1684 (char *)hmacbuff, hash->hash_len);
1686 1685
1687 1686 if (result != CRYPTO_SUCCESS) {
1688 1687 cmn_err(CE_WARN, "aes_encrypt: do_hmac failed - error %0x",
1689 1688 result);
1690 1689 goto cleanup;
1691 1690 }
1692 1691 /* Encrypt using AES-CBC-CTS */
1693 1692 result = aes_cbc_cts_encrypt(tmi, mp->b_rptr,
1694 1693 inlen + DEFAULT_AES_BLOCKLEN);
1695 1694
1696 1695 if (result != CRYPTO_SUCCESS) {
1697 1696 cmn_err(CE_WARN, "aes_encrypt: aes_cbc_cts_encrypt "
1698 1697 "failed - error %0x", result);
1699 1698 goto cleanup;
1700 1699 }
1701 1700
1702 1701 /* copy the truncated HMAC to the end of the mblk */
1703 1702 bcopy(hmacbuff, mp->b_rptr + DEFAULT_AES_BLOCKLEN + inlen,
1704 1703 AES_TRUNCATED_HMAC_LEN);
1705 1704
1706 1705 mp->b_wptr = mp->b_rptr + cipherlen;
1707 1706
1708 1707 /*
1709 1708 * The final block of cipher text (not the HMAC) is used
1710 1709 * as the next IV.
1711 1710 */
1712 1711 if (tmi->enc_data.ivec_usage != IVEC_NEVER &&
1713 1712 tmi->enc_data.ivec != NULL) {
1714 1713 int nblocks = (inlen + 2 * DEFAULT_AES_BLOCKLEN - 1) /
1715 1714 DEFAULT_AES_BLOCKLEN;
1716 1715
1717 1716 bcopy(mp->b_rptr + (nblocks - 2) * DEFAULT_AES_BLOCKLEN,
1718 1717 tmi->enc_data.ivec, DEFAULT_AES_BLOCKLEN);
1719 1718 }
1720 1719
1721 1720 cleanup:
1722 1721 if (result != CRYPTO_SUCCESS) {
1723 1722 mp->b_datap->db_type = M_ERROR;
1724 1723 mp->b_rptr = mp->b_datap->db_base;
1725 1724 *mp->b_rptr = EIO;
1726 1725 mp->b_wptr = mp->b_rptr + sizeof (char);
1727 1726 freemsg(mp->b_cont);
1728 1727 mp->b_cont = NULL;
1729 1728 qreply(WR(q), mp);
1730 1729 return (NULL);
1731 1730 }
1732 1731 return (mp);
1733 1732 }
1734 1733
1735 1734 /*
1736 1735 * ARCFOUR-HMAC-MD5 decrypt
1737 1736 *
1738 1737 * format of ciphertext when using ARCFOUR-HMAC-MD5
1739 1738 * +-----------+------------+------------+
1740 1739 * | hmac | confounder | msg-data |
1741 1740 * +-----------+------------+------------+
1742 1741 *
1743 1742 */
1744 1743 static mblk_t *
1745 1744 arcfour_hmac_md5_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp,
1746 1745 hash_info_t *hash)
1747 1746 {
1748 1747 int result;
1749 1748 size_t cipherlen;
1750 1749 size_t inlen;
1751 1750 size_t saltlen;
1752 1751 crypto_key_t k1, k2;
1753 1752 crypto_data_t indata;
1754 1753 iovec_t v1;
1755 1754 uchar_t ms_exp[9] = {0xab, 0xab, 0xab, 0xab, 0xab,
1756 1755 0xab, 0xab, 0xab, 0xab };
1757 1756 uchar_t k1data[CRYPT_ARCFOUR_KEYBYTES];
1758 1757 uchar_t k2data[CRYPT_ARCFOUR_KEYBYTES];
1759 1758 uchar_t cksum[MD5_HASHSIZE];
1760 1759 uchar_t saltdata[CRYPT_ARCFOUR_KEYBYTES];
1761 1760 crypto_mechanism_t mech;
1762 1761 int usage;
1763 1762
1764 1763 bzero(&indata, sizeof (indata));
1765 1764
1766 1765 /* The usage constant is 1026 for all "old" rcmd mode operations */
1767 1766 if (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V1)
1768 1767 usage = RCMDV1_USAGE;
1769 1768 else
1770 1769 usage = ARCFOUR_DECRYPT_USAGE;
1771 1770
1772 1771 /*
1773 1772 * The size at this point should be the size of
1774 1773 * all the plaintext plus the optional plaintext length
1775 1774 * needed for RCMD V2 mode. There should also be room
1776 1775 * at the head of the mblk for the confounder and hash info.
1777 1776 */
1778 1777 inlen = (size_t)MBLKL(mp);
1779 1778
1780 1779 /*
1781 1780 * The cipherlen does not include the HMAC at the
1782 1781 * head of the buffer.
1783 1782 */
1784 1783 cipherlen = inlen - hash->hash_len;
1785 1784
1786 1785 ASSERT(MBLKSIZE(mp) >= cipherlen);
1787 1786 if (tmi->dec_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) {
1788 1787 bcopy(ARCFOUR_EXP_SALT, saltdata, strlen(ARCFOUR_EXP_SALT));
1789 1788 saltdata[9] = 0;
1790 1789 saltdata[10] = usage & 0xff;
1791 1790 saltdata[11] = (usage >> 8) & 0xff;
1792 1791 saltdata[12] = (usage >> 16) & 0xff;
1793 1792 saltdata[13] = (usage >> 24) & 0xff;
1794 1793 saltlen = 14;
1795 1794 } else {
1796 1795 saltdata[0] = usage & 0xff;
1797 1796 saltdata[1] = (usage >> 8) & 0xff;
1798 1797 saltdata[2] = (usage >> 16) & 0xff;
1799 1798 saltdata[3] = (usage >> 24) & 0xff;
1800 1799 saltlen = 4;
1801 1800 }
1802 1801 /*
1803 1802 * Use the salt value to create a key to be used
1804 1803 * for subsequent HMAC operations.
1805 1804 */
1806 1805 result = do_hmac(md5_hmac_mech,
1807 1806 tmi->dec_data.ckey,
1808 1807 (char *)saltdata, saltlen,
1809 1808 (char *)k1data, sizeof (k1data));
1810 1809 if (result != CRYPTO_SUCCESS) {
1811 1810 cmn_err(CE_WARN,
1812 1811 "arcfour_hmac_md5_decrypt: do_hmac(k1)"
1813 1812 "failed - error %0x", result);
1814 1813 goto cleanup;
1815 1814 }
1816 1815 bcopy(k1data, k2data, sizeof (k1data));
1817 1816
1818 1817 /*
1819 1818 * For the neutered MS RC4 encryption type,
1820 1819 * set the trailing 9 bytes to 0xab per the
1821 1820 * RC4-HMAC spec.
1822 1821 */
1823 1822 if (tmi->dec_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) {
1824 1823 bcopy((void *)&k1data[7], ms_exp, sizeof (ms_exp));
1825 1824 }
1826 1825
1827 1826 mech.cm_type = tmi->dec_data.mech_type;
1828 1827 mech.cm_param = NULL;
1829 1828 mech.cm_param_len = 0;
1830 1829
1831 1830 /*
1832 1831 * If we have not yet initialized the decryption key,
1833 1832 * context, and template, do it now.
1834 1833 */
1835 1834 if (tmi->dec_data.ctx == NULL ||
1836 1835 (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V1)) {
1837 1836 k1.ck_format = CRYPTO_KEY_RAW;
1838 1837 k1.ck_length = CRYPT_ARCFOUR_KEYBYTES * 8;
1839 1838 k1.ck_data = k1data;
1840 1839
1841 1840 tmi->dec_data.d_encr_key.ck_format = CRYPTO_KEY_RAW;
1842 1841 tmi->dec_data.d_encr_key.ck_length = k1.ck_length;
1843 1842 if (tmi->dec_data.d_encr_key.ck_data == NULL)
1844 1843 tmi->dec_data.d_encr_key.ck_data = kmem_zalloc(
1845 1844 CRYPT_ARCFOUR_KEYBYTES, KM_SLEEP);
1846 1845
1847 1846 /*
1848 1847 * HMAC operation creates the encryption
1849 1848 * key to be used for the decrypt operations.
1850 1849 */
1851 1850 result = do_hmac(md5_hmac_mech, &k1,
1852 1851 (char *)mp->b_rptr, hash->hash_len,
1853 1852 (char *)tmi->dec_data.d_encr_key.ck_data,
1854 1853 CRYPT_ARCFOUR_KEYBYTES);
1855 1854
1856 1855
1857 1856 if (result != CRYPTO_SUCCESS) {
1858 1857 cmn_err(CE_WARN,
1859 1858 "arcfour_hmac_md5_decrypt: do_hmac(k3)"
1860 1859 "failed - error %0x", result);
1861 1860 goto cleanup;
1862 1861 }
1863 1862 }
1864 1863
1865 1864 tmi->dec_data.enc_tmpl = NULL;
1866 1865
1867 1866 if (tmi->dec_data.ctx == NULL &&
1868 1867 (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V2)) {
1869 1868 /*
1870 1869 * Only create a template if we are doing
1871 1870 * chaining from block to block.
1872 1871 */
1873 1872 result = crypto_create_ctx_template(&mech,
1874 1873 &tmi->dec_data.d_encr_key,
1875 1874 &tmi->dec_data.enc_tmpl,
1876 1875 KM_SLEEP);
1877 1876 if (result == CRYPTO_NOT_SUPPORTED) {
1878 1877 tmi->dec_data.enc_tmpl = NULL;
1879 1878 } else if (result != CRYPTO_SUCCESS) {
1880 1879 cmn_err(CE_WARN,
1881 1880 "arcfour_hmac_md5_decrypt: "
1882 1881 "failed to create dec template "
1883 1882 "for RC4 encrypt: %0x", result);
1884 1883 goto cleanup;
1885 1884 }
1886 1885
1887 1886 result = crypto_decrypt_init(&mech,
1888 1887 &tmi->dec_data.d_encr_key,
1889 1888 tmi->dec_data.enc_tmpl,
1890 1889 &tmi->dec_data.ctx, NULL);
1891 1890
1892 1891 if (result != CRYPTO_SUCCESS) {
1893 1892 cmn_err(CE_WARN, "crypto_decrypt_init failed:"
1894 1893 " %0x", result);
1895 1894 goto cleanup;
1896 1895 }
1897 1896 }
1898 1897
1899 1898 /* adjust the rptr so we don't decrypt the original hmac field */
1900 1899
1901 1900 v1.iov_base = (char *)mp->b_rptr + hash->hash_len;
1902 1901 v1.iov_len = cipherlen;
1903 1902
1904 1903 indata.cd_format = CRYPTO_DATA_RAW;
1905 1904 indata.cd_offset = 0;
1906 1905 indata.cd_length = cipherlen;
1907 1906 indata.cd_raw = v1;
1908 1907
1909 1908 if (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V2)
1910 1909 result = crypto_decrypt_update(tmi->dec_data.ctx,
1911 1910 &indata, NULL, NULL);
1912 1911 else
1913 1912 result = crypto_decrypt(&mech, &indata,
1914 1913 &tmi->dec_data.d_encr_key, NULL, NULL, NULL);
1915 1914
1916 1915 if (result != CRYPTO_SUCCESS) {
1917 1916 cmn_err(CE_WARN, "crypto_decrypt_update failed:"
1918 1917 " %0x", result);
1919 1918 goto cleanup;
1920 1919 }
1921 1920
1922 1921 k2.ck_format = CRYPTO_KEY_RAW;
1923 1922 k2.ck_length = sizeof (k2data) * 8;
1924 1923 k2.ck_data = k2data;
1925 1924
1926 1925 result = do_hmac(md5_hmac_mech,
1927 1926 &k2,
1928 1927 (char *)mp->b_rptr + hash->hash_len, cipherlen,
1929 1928 (char *)cksum, hash->hash_len);
1930 1929
1931 1930 if (result != CRYPTO_SUCCESS) {
1932 1931 cmn_err(CE_WARN,
1933 1932 "arcfour_hmac_md5_decrypt: do_hmac(k2)"
1934 1933 "failed - error %0x", result);
1935 1934 goto cleanup;
1936 1935 }
1937 1936
1938 1937 if (bcmp(cksum, mp->b_rptr, hash->hash_len) != 0) {
1939 1938 cmn_err(CE_WARN, "arcfour_decrypt HMAC comparison failed");
1940 1939 result = -1;
1941 1940 goto cleanup;
1942 1941 }
1943 1942
1944 1943 /*
1945 1944 * adjust the start of the mblk to skip over the
1946 1945 * hash and confounder.
1947 1946 */
1948 1947 mp->b_rptr += hash->hash_len + hash->confound_len;
1949 1948
1950 1949 cleanup:
1951 1950 bzero(k1data, sizeof (k1data));
1952 1951 bzero(k2data, sizeof (k2data));
1953 1952 bzero(cksum, sizeof (cksum));
1954 1953 bzero(saltdata, sizeof (saltdata));
1955 1954 if (result != CRYPTO_SUCCESS) {
1956 1955 mp->b_datap->db_type = M_ERROR;
1957 1956 mp->b_rptr = mp->b_datap->db_base;
1958 1957 *mp->b_rptr = EIO;
1959 1958 mp->b_wptr = mp->b_rptr + sizeof (char);
1960 1959 freemsg(mp->b_cont);
1961 1960 mp->b_cont = NULL;
1962 1961 qreply(WR(q), mp);
1963 1962 return (NULL);
1964 1963 }
1965 1964 return (mp);
1966 1965 }
1967 1966
1968 1967 /*
1969 1968 * ARCFOUR-HMAC-MD5 encrypt
1970 1969 *
1971 1970 * format of ciphertext when using ARCFOUR-HMAC-MD5
1972 1971 * +-----------+------------+------------+
1973 1972 * | hmac | confounder | msg-data |
1974 1973 * +-----------+------------+------------+
1975 1974 *
1976 1975 */
1977 1976 static mblk_t *
1978 1977 arcfour_hmac_md5_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp,
1979 1978 hash_info_t *hash)
1980 1979 {
1981 1980 int result;
1982 1981 size_t cipherlen;
1983 1982 size_t inlen;
1984 1983 size_t saltlen;
1985 1984 crypto_key_t k1, k2;
1986 1985 crypto_data_t indata;
1987 1986 iovec_t v1;
1988 1987 uchar_t ms_exp[9] = {0xab, 0xab, 0xab, 0xab, 0xab,
1989 1988 0xab, 0xab, 0xab, 0xab };
1990 1989 uchar_t k1data[CRYPT_ARCFOUR_KEYBYTES];
1991 1990 uchar_t k2data[CRYPT_ARCFOUR_KEYBYTES];
1992 1991 uchar_t saltdata[CRYPT_ARCFOUR_KEYBYTES];
1993 1992 crypto_mechanism_t mech;
1994 1993 int usage;
1995 1994
1996 1995 bzero(&indata, sizeof (indata));
1997 1996
1998 1997 /* The usage constant is 1026 for all "old" rcmd mode operations */
1999 1998 if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V1)
2000 1999 usage = RCMDV1_USAGE;
2001 2000 else
2002 2001 usage = ARCFOUR_ENCRYPT_USAGE;
2003 2002
2004 2003 mech.cm_type = tmi->enc_data.mech_type;
2005 2004 mech.cm_param = NULL;
2006 2005 mech.cm_param_len = 0;
2007 2006
2008 2007 /*
2009 2008 * The size at this point should be the size of
2010 2009 * all the plaintext plus the optional plaintext length
2011 2010 * needed for RCMD V2 mode. There should also be room
2012 2011 * at the head of the mblk for the confounder and hash info.
2013 2012 */
2014 2013 inlen = (size_t)MBLKL(mp);
2015 2014
2016 2015 cipherlen = encrypt_size(&tmi->enc_data, inlen);
2017 2016
2018 2017 ASSERT(MBLKSIZE(mp) >= cipherlen);
2019 2018
2020 2019 /*
2021 2020 * Shift the rptr back enough to insert
2022 2021 * the confounder and hash.
2023 2022 */
2024 2023 mp->b_rptr -= (hash->confound_len + hash->hash_len);
2025 2024
2026 2025 /* zero out the hash area */
2027 2026 bzero(mp->b_rptr, (size_t)hash->hash_len);
2028 2027
2029 2028 if (cipherlen > inlen) {
2030 2029 bzero(mp->b_wptr, MBLKTAIL(mp));
2031 2030 }
2032 2031
2033 2032 if (tmi->enc_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) {
2034 2033 bcopy(ARCFOUR_EXP_SALT, saltdata, strlen(ARCFOUR_EXP_SALT));
2035 2034 saltdata[9] = 0;
2036 2035 saltdata[10] = usage & 0xff;
2037 2036 saltdata[11] = (usage >> 8) & 0xff;
2038 2037 saltdata[12] = (usage >> 16) & 0xff;
2039 2038 saltdata[13] = (usage >> 24) & 0xff;
2040 2039 saltlen = 14;
2041 2040 } else {
2042 2041 saltdata[0] = usage & 0xff;
2043 2042 saltdata[1] = (usage >> 8) & 0xff;
2044 2043 saltdata[2] = (usage >> 16) & 0xff;
2045 2044 saltdata[3] = (usage >> 24) & 0xff;
2046 2045 saltlen = 4;
2047 2046 }
2048 2047 /*
2049 2048 * Use the salt value to create a key to be used
2050 2049 * for subsequent HMAC operations.
2051 2050 */
2052 2051 result = do_hmac(md5_hmac_mech,
2053 2052 tmi->enc_data.ckey,
2054 2053 (char *)saltdata, saltlen,
2055 2054 (char *)k1data, sizeof (k1data));
2056 2055 if (result != CRYPTO_SUCCESS) {
2057 2056 cmn_err(CE_WARN,
2058 2057 "arcfour_hmac_md5_encrypt: do_hmac(k1)"
2059 2058 "failed - error %0x", result);
2060 2059 goto cleanup;
2061 2060 }
2062 2061
2063 2062 bcopy(k1data, k2data, sizeof (k2data));
2064 2063
2065 2064 /*
2066 2065 * For the neutered MS RC4 encryption type,
2067 2066 * set the trailing 9 bytes to 0xab per the
2068 2067 * RC4-HMAC spec.
2069 2068 */
2070 2069 if (tmi->enc_data.method == CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP) {
2071 2070 bcopy((void *)&k1data[7], ms_exp, sizeof (ms_exp));
2072 2071 }
2073 2072
2074 2073 /*
2075 2074 * Get the confounder bytes.
2076 2075 */
2077 2076 (void) random_get_pseudo_bytes(
2078 2077 (uint8_t *)(mp->b_rptr + hash->hash_len),
2079 2078 (size_t)hash->confound_len);
2080 2079
2081 2080 k2.ck_data = k2data;
2082 2081 k2.ck_format = CRYPTO_KEY_RAW;
2083 2082 k2.ck_length = sizeof (k2data) * 8;
2084 2083
2085 2084 /*
2086 2085 * This writes the HMAC to the hash area in the
2087 2086 * mblk. The key used is the one just created by
2088 2087 * the previous HMAC operation.
2089 2088 * The data being processed is the confounder bytes
2090 2089 * PLUS the input plaintext.
2091 2090 */
2092 2091 result = do_hmac(md5_hmac_mech, &k2,
2093 2092 (char *)mp->b_rptr + hash->hash_len,
2094 2093 hash->confound_len + inlen,
2095 2094 (char *)mp->b_rptr, hash->hash_len);
2096 2095 if (result != CRYPTO_SUCCESS) {
2097 2096 cmn_err(CE_WARN,
2098 2097 "arcfour_hmac_md5_encrypt: do_hmac(k2)"
2099 2098 "failed - error %0x", result);
2100 2099 goto cleanup;
2101 2100 }
2102 2101 /*
2103 2102 * Because of the odd way that MIT uses RC4 keys
2104 2103 * on the rlogin stream, we only need to create
2105 2104 * this key once.
2106 2105 * However, if using "old" rcmd mode, we need to do
2107 2106 * it every time.
2108 2107 */
2109 2108 if (tmi->enc_data.ctx == NULL ||
2110 2109 (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V1)) {
2111 2110 crypto_key_t *key = &tmi->enc_data.d_encr_key;
2112 2111
2113 2112 k1.ck_data = k1data;
2114 2113 k1.ck_format = CRYPTO_KEY_RAW;
2115 2114 k1.ck_length = sizeof (k1data) * 8;
2116 2115
2117 2116 key->ck_format = CRYPTO_KEY_RAW;
2118 2117 key->ck_length = k1.ck_length;
2119 2118 if (key->ck_data == NULL)
2120 2119 key->ck_data = kmem_zalloc(
2121 2120 CRYPT_ARCFOUR_KEYBYTES, KM_SLEEP);
2122 2121
2123 2122 /*
2124 2123 * The final HMAC operation creates the encryption
2125 2124 * key to be used for the encrypt operation.
2126 2125 */
2127 2126 result = do_hmac(md5_hmac_mech, &k1,
2128 2127 (char *)mp->b_rptr, hash->hash_len,
2129 2128 (char *)key->ck_data, CRYPT_ARCFOUR_KEYBYTES);
2130 2129
2131 2130 if (result != CRYPTO_SUCCESS) {
2132 2131 cmn_err(CE_WARN,
2133 2132 "arcfour_hmac_md5_encrypt: do_hmac(k3)"
2134 2133 "failed - error %0x", result);
2135 2134 goto cleanup;
2136 2135 }
2137 2136 }
2138 2137
2139 2138 /*
2140 2139 * If the context has not been initialized, do it now.
2141 2140 */
2142 2141 if (tmi->enc_data.ctx == NULL &&
2143 2142 (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2)) {
2144 2143 /*
2145 2144 * Only create a template if we are doing
2146 2145 * chaining from block to block.
2147 2146 */
2148 2147 result = crypto_create_ctx_template(&mech,
2149 2148 &tmi->enc_data.d_encr_key,
2150 2149 &tmi->enc_data.enc_tmpl,
2151 2150 KM_SLEEP);
2152 2151 if (result == CRYPTO_NOT_SUPPORTED) {
2153 2152 tmi->enc_data.enc_tmpl = NULL;
2154 2153 } else if (result != CRYPTO_SUCCESS) {
2155 2154 cmn_err(CE_WARN, "failed to create enc template "
2156 2155 "for RC4 encrypt: %0x", result);
2157 2156 goto cleanup;
2158 2157 }
2159 2158
2160 2159 result = crypto_encrypt_init(&mech,
2161 2160 &tmi->enc_data.d_encr_key,
2162 2161 tmi->enc_data.enc_tmpl,
2163 2162 &tmi->enc_data.ctx, NULL);
2164 2163 if (result != CRYPTO_SUCCESS) {
2165 2164 cmn_err(CE_WARN, "crypto_encrypt_init failed:"
2166 2165 " %0x", result);
2167 2166 goto cleanup;
2168 2167 }
2169 2168 }
2170 2169 v1.iov_base = (char *)mp->b_rptr + hash->hash_len;
2171 2170 v1.iov_len = hash->confound_len + inlen;
2172 2171
2173 2172 indata.cd_format = CRYPTO_DATA_RAW;
2174 2173 indata.cd_offset = 0;
2175 2174 indata.cd_length = hash->confound_len + inlen;
2176 2175 indata.cd_raw = v1;
2177 2176
2178 2177 if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2)
2179 2178 result = crypto_encrypt_update(tmi->enc_data.ctx,
2180 2179 &indata, NULL, NULL);
2181 2180 else
2182 2181 result = crypto_encrypt(&mech, &indata,
2183 2182 &tmi->enc_data.d_encr_key, NULL,
2184 2183 NULL, NULL);
2185 2184
2186 2185 if (result != CRYPTO_SUCCESS) {
2187 2186 cmn_err(CE_WARN, "crypto_encrypt_update failed: 0x%0x",
2188 2187 result);
2189 2188 }
2190 2189
2191 2190 cleanup:
2192 2191 bzero(k1data, sizeof (k1data));
2193 2192 bzero(k2data, sizeof (k2data));
2194 2193 bzero(saltdata, sizeof (saltdata));
2195 2194 if (result != CRYPTO_SUCCESS) {
2196 2195 mp->b_datap->db_type = M_ERROR;
2197 2196 mp->b_rptr = mp->b_datap->db_base;
2198 2197 *mp->b_rptr = EIO;
2199 2198 mp->b_wptr = mp->b_rptr + sizeof (char);
2200 2199 freemsg(mp->b_cont);
2201 2200 mp->b_cont = NULL;
2202 2201 qreply(WR(q), mp);
2203 2202 return (NULL);
2204 2203 }
2205 2204 return (mp);
2206 2205 }
2207 2206
2208 2207 /*
2209 2208 * DES-CBC-[HASH] encrypt
2210 2209 *
2211 2210 * Needed to support userland apps that must support Kerberos V5
2212 2211 * encryption DES-CBC encryption modes.
2213 2212 *
2214 2213 * The HASH values supported are RAW(NULL), MD5, CRC32, and SHA1
2215 2214 *
2216 2215 * format of ciphertext for DES-CBC functions, per RFC1510 is:
2217 2216 * +-----------+----------+-------------+-----+
2218 2217 * |confounder | cksum | msg-data | pad |
2219 2218 * +-----------+----------+-------------+-----+
2220 2219 *
2221 2220 * format of ciphertext when using DES3-SHA1-HMAC
2222 2221 * +-----------+----------+-------------+-----+
2223 2222 * |confounder | msg-data | hmac | pad |
2224 2223 * +-----------+----------+-------------+-----+
2225 2224 *
2226 2225 * The confounder is 8 bytes of random data.
2227 2226 * The cksum depends on the hash being used.
2228 2227 * 4 bytes for CRC32
2229 2228 * 16 bytes for MD5
2230 2229 * 20 bytes for SHA1
2231 2230 * 0 bytes for RAW
2232 2231 *
2233 2232 */
2234 2233 static mblk_t *
2235 2234 des_cbc_encrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, hash_info_t *hash)
2236 2235 {
2237 2236 int result;
2238 2237 size_t cipherlen;
2239 2238 size_t inlen;
2240 2239 size_t plainlen;
2241 2240
2242 2241 /*
2243 2242 * The size at this point should be the size of
2244 2243 * all the plaintext plus the optional plaintext length
2245 2244 * needed for RCMD V2 mode. There should also be room
2246 2245 * at the head of the mblk for the confounder and hash info.
2247 2246 */
2248 2247 inlen = (size_t)MBLKL(mp);
2249 2248
2250 2249 /*
2251 2250 * The output size will be a multiple of 8 because this algorithm
2252 2251 * only works on 8 byte chunks.
2253 2252 */
2254 2253 cipherlen = encrypt_size(&tmi->enc_data, inlen);
2255 2254
2256 2255 ASSERT(MBLKSIZE(mp) >= cipherlen);
2257 2256
2258 2257 if (cipherlen > inlen) {
2259 2258 bzero(mp->b_wptr, MBLKTAIL(mp));
2260 2259 }
2261 2260
2262 2261 /*
2263 2262 * Shift the rptr back enough to insert
2264 2263 * the confounder and hash.
2265 2264 */
2266 2265 if (tmi->enc_data.method == CRYPT_METHOD_DES3_CBC_SHA1) {
2267 2266 mp->b_rptr -= hash->confound_len;
2268 2267 } else {
2269 2268 mp->b_rptr -= (hash->confound_len + hash->hash_len);
2270 2269
2271 2270 /* zero out the hash area */
2272 2271 bzero(mp->b_rptr + hash->confound_len, (size_t)hash->hash_len);
2273 2272 }
2274 2273
2275 2274 /* get random confounder from our friend, the 'random' module */
2276 2275 if (hash->confound_len > 0) {
2277 2276 (void) random_get_pseudo_bytes((uint8_t *)mp->b_rptr,
2278 2277 (size_t)hash->confound_len);
2279 2278 }
2280 2279
2281 2280 /*
2282 2281 * For 3DES we calculate an HMAC later.
2283 2282 */
2284 2283 if (tmi->enc_data.method != CRYPT_METHOD_DES3_CBC_SHA1) {
2285 2284 /* calculate chksum of confounder + input */
2286 2285 if (hash->hash_len > 0 && hash->hashfunc != NULL) {
2287 2286 uchar_t cksum[MAX_CKSUM_LEN];
2288 2287
2289 2288 result = hash->hashfunc(cksum, mp->b_rptr,
2290 2289 cipherlen);
2291 2290 if (result != CRYPTO_SUCCESS) {
2292 2291 goto failure;
2293 2292 }
2294 2293
2295 2294 /* put hash in place right after the confounder */
2296 2295 bcopy(cksum, (mp->b_rptr + hash->confound_len),
2297 2296 (size_t)hash->hash_len);
2298 2297 }
2299 2298 }
2300 2299 /*
2301 2300 * In order to support the "old" Kerberos RCMD protocol,
2302 2301 * we must use the IVEC 3 different ways:
2303 2302 * IVEC_REUSE = keep using the same IV each time, this is
2304 2303 * ugly and insecure, but necessary for
2305 2304 * backwards compatibility with existing MIT code.
2306 2305 * IVEC_ONETIME = Use the ivec as initialized when the crypto
2307 2306 * was setup (see setup_crypto routine).
2308 2307 * IVEC_NEVER = never use an IVEC, use a bunch of 0's as the IV (yuk).
2309 2308 */
2310 2309 if (tmi->enc_data.ivec_usage == IVEC_NEVER) {
2311 2310 bzero(tmi->enc_data.block, tmi->enc_data.blocklen);
2312 2311 } else if (tmi->enc_data.ivec_usage == IVEC_REUSE) {
2313 2312 bcopy(tmi->enc_data.ivec, tmi->enc_data.block,
2314 2313 tmi->enc_data.blocklen);
2315 2314 }
2316 2315
2317 2316 if (tmi->enc_data.method == CRYPT_METHOD_DES3_CBC_SHA1) {
2318 2317 /*
2319 2318 * The input length already included the hash size,
2320 2319 * don't include this in the plaintext length
2321 2320 * calculations.
2322 2321 */
2323 2322 plainlen = cipherlen - hash->hash_len;
2324 2323
2325 2324 mp->b_wptr = mp->b_rptr + plainlen;
2326 2325
2327 2326 result = kef_encr_hmac(&tmi->enc_data,
2328 2327 (void *)mp, (size_t)plainlen,
2329 2328 (char *)(mp->b_rptr + plainlen),
2330 2329 hash->hash_len);
2331 2330 } else {
2332 2331 ASSERT(mp->b_rptr + cipherlen <= DB_LIM(mp));
2333 2332 mp->b_wptr = mp->b_rptr + cipherlen;
2334 2333 result = kef_crypt(&tmi->enc_data, (void *)mp,
2335 2334 CRYPTO_DATA_MBLK, (size_t)cipherlen,
2336 2335 CRYPT_ENCRYPT);
2337 2336 }
2338 2337 failure:
2339 2338 if (result != CRYPTO_SUCCESS) {
2340 2339 #ifdef DEBUG
2341 2340 cmn_err(CE_WARN,
2342 2341 "des_cbc_encrypt: kef_crypt encrypt "
2343 2342 "failed (len: %ld) - error %0x",
2344 2343 cipherlen, result);
2345 2344 #endif
2346 2345 mp->b_datap->db_type = M_ERROR;
2347 2346 mp->b_rptr = mp->b_datap->db_base;
2348 2347 *mp->b_rptr = EIO;
2349 2348 mp->b_wptr = mp->b_rptr + sizeof (char);
2350 2349 freemsg(mp->b_cont);
2351 2350 mp->b_cont = NULL;
2352 2351 qreply(WR(q), mp);
2353 2352 return (NULL);
2354 2353 } else if (tmi->enc_data.ivec_usage == IVEC_ONETIME) {
2355 2354 /*
2356 2355 * Because we are using KEF, we must manually
2357 2356 * update our IV.
2358 2357 */
2359 2358 bcopy(mp->b_wptr - tmi->enc_data.ivlen,
2360 2359 tmi->enc_data.block, tmi->enc_data.ivlen);
2361 2360 }
2362 2361 if (tmi->enc_data.method == CRYPT_METHOD_DES3_CBC_SHA1) {
2363 2362 mp->b_wptr = mp->b_rptr + cipherlen;
2364 2363 }
2365 2364
2366 2365 return (mp);
2367 2366 }
2368 2367
2369 2368 /*
2370 2369 * des_cbc_decrypt
2371 2370 *
2372 2371 *
2373 2372 * Needed to support userland apps that must support Kerberos V5
2374 2373 * encryption DES-CBC decryption modes.
2375 2374 *
2376 2375 * The HASH values supported are RAW(NULL), MD5, CRC32, and SHA1
2377 2376 *
2378 2377 * format of ciphertext for DES-CBC functions, per RFC1510 is:
2379 2378 * +-----------+----------+-------------+-----+
2380 2379 * |confounder | cksum | msg-data | pad |
2381 2380 * +-----------+----------+-------------+-----+
2382 2381 *
2383 2382 * format of ciphertext when using DES3-SHA1-HMAC
2384 2383 * +-----------+----------+-------------+-----+
2385 2384 * |confounder | msg-data | hmac | pad |
2386 2385 * +-----------+----------+-------------+-----+
2387 2386 *
2388 2387 * The confounder is 8 bytes of random data.
2389 2388 * The cksum depends on the hash being used.
2390 2389 * 4 bytes for CRC32
2391 2390 * 16 bytes for MD5
2392 2391 * 20 bytes for SHA1
2393 2392 * 0 bytes for RAW
2394 2393 *
2395 2394 */
2396 2395 static mblk_t *
2397 2396 des_cbc_decrypt(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, hash_info_t *hash)
2398 2397 {
2399 2398 uint_t inlen, datalen;
2400 2399 int result = 0;
2401 2400 uchar_t *optr = NULL;
2402 2401 uchar_t cksum[MAX_CKSUM_LEN], newcksum[MAX_CKSUM_LEN];
2403 2402 uchar_t nextiv[DEFAULT_DES_BLOCKLEN];
2404 2403
2405 2404 /* Compute adjusted size */
2406 2405 inlen = MBLKL(mp);
2407 2406
2408 2407 optr = mp->b_rptr;
2409 2408
2410 2409 /*
2411 2410 * In order to support the "old" Kerberos RCMD protocol,
2412 2411 * we must use the IVEC 3 different ways:
2413 2412 * IVEC_REUSE = keep using the same IV each time, this is
2414 2413 * ugly and insecure, but necessary for
2415 2414 * backwards compatibility with existing MIT code.
2416 2415 * IVEC_ONETIME = Use the ivec as initialized when the crypto
2417 2416 * was setup (see setup_crypto routine).
2418 2417 * IVEC_NEVER = never use an IVEC, use a bunch of 0's as the IV (yuk).
2419 2418 */
2420 2419 if (tmi->dec_data.ivec_usage == IVEC_NEVER)
2421 2420 bzero(tmi->dec_data.block, tmi->dec_data.blocklen);
2422 2421 else if (tmi->dec_data.ivec_usage == IVEC_REUSE)
2423 2422 bcopy(tmi->dec_data.ivec, tmi->dec_data.block,
2424 2423 tmi->dec_data.blocklen);
2425 2424
2426 2425 if (tmi->dec_data.method == CRYPT_METHOD_DES3_CBC_SHA1) {
2427 2426 /*
2428 2427 * Do not decrypt the HMAC at the end
2429 2428 */
2430 2429 int decrypt_len = inlen - hash->hash_len;
2431 2430
2432 2431 /*
2433 2432 * Move the wptr so the mblk appears to end
2434 2433 * BEFORE the HMAC section.
2435 2434 */
2436 2435 mp->b_wptr = mp->b_rptr + decrypt_len;
2437 2436
2438 2437 /*
2439 2438 * Because we are using KEF, we must manually update our
2440 2439 * IV.
2441 2440 */
2442 2441 if (tmi->dec_data.ivec_usage == IVEC_ONETIME) {
2443 2442 bcopy(mp->b_rptr + decrypt_len - tmi->dec_data.ivlen,
2444 2443 nextiv, tmi->dec_data.ivlen);
2445 2444 }
2446 2445
2447 2446 result = kef_decr_hmac(&tmi->dec_data, mp, decrypt_len,
2448 2447 (char *)newcksum, hash->hash_len);
2449 2448 } else {
2450 2449 /*
2451 2450 * Because we are using KEF, we must manually update our
2452 2451 * IV.
2453 2452 */
2454 2453 if (tmi->dec_data.ivec_usage == IVEC_ONETIME) {
2455 2454 bcopy(mp->b_wptr - tmi->enc_data.ivlen, nextiv,
2456 2455 tmi->dec_data.ivlen);
2457 2456 }
2458 2457 result = kef_crypt(&tmi->dec_data, (void *)mp,
2459 2458 CRYPTO_DATA_MBLK, (size_t)inlen, CRYPT_DECRYPT);
2460 2459 }
2461 2460 if (result != CRYPTO_SUCCESS) {
2462 2461 #ifdef DEBUG
2463 2462 cmn_err(CE_WARN,
2464 2463 "des_cbc_decrypt: kef_crypt decrypt "
2465 2464 "failed - error %0x", result);
2466 2465 #endif
2467 2466 mp->b_datap->db_type = M_ERROR;
2468 2467 mp->b_rptr = mp->b_datap->db_base;
2469 2468 *mp->b_rptr = EIO;
2470 2469 mp->b_wptr = mp->b_rptr + sizeof (char);
2471 2470 freemsg(mp->b_cont);
2472 2471 mp->b_cont = NULL;
2473 2472 qreply(WR(q), mp);
2474 2473 return (NULL);
2475 2474 }
2476 2475
2477 2476 /*
2478 2477 * Manually update the IV, KEF does not track this for us.
2479 2478 */
2480 2479 if (tmi->dec_data.ivec_usage == IVEC_ONETIME) {
2481 2480 bcopy(nextiv, tmi->dec_data.block, tmi->dec_data.ivlen);
2482 2481 }
2483 2482
2484 2483 /* Verify the checksum(if necessary) */
2485 2484 if (hash->hash_len > 0) {
2486 2485 if (tmi->dec_data.method == CRYPT_METHOD_DES3_CBC_SHA1) {
2487 2486 bcopy(mp->b_rptr + inlen - hash->hash_len, cksum,
2488 2487 hash->hash_len);
2489 2488 } else {
2490 2489 bcopy(optr + hash->confound_len, cksum, hash->hash_len);
2491 2490
2492 2491 /* zero the cksum in the buffer */
2493 2492 ASSERT(optr + hash->confound_len + hash->hash_len <=
2494 2493 DB_LIM(mp));
2495 2494 bzero(optr + hash->confound_len, hash->hash_len);
2496 2495
2497 2496 /* calculate MD5 chksum of confounder + input */
2498 2497 if (hash->hashfunc) {
2499 2498 (void) hash->hashfunc(newcksum, optr, inlen);
2500 2499 }
2501 2500 }
2502 2501
2503 2502 if (bcmp(cksum, newcksum, hash->hash_len)) {
2504 2503 #ifdef DEBUG
2505 2504 cmn_err(CE_WARN, "des_cbc_decrypt: checksum "
2506 2505 "verification failed");
2507 2506 #endif
2508 2507 mp->b_datap->db_type = M_ERROR;
2509 2508 mp->b_rptr = mp->b_datap->db_base;
2510 2509 *mp->b_rptr = EIO;
2511 2510 mp->b_wptr = mp->b_rptr + sizeof (char);
2512 2511 freemsg(mp->b_cont);
2513 2512 mp->b_cont = NULL;
2514 2513 qreply(WR(q), mp);
2515 2514 return (NULL);
2516 2515 }
2517 2516 }
2518 2517
2519 2518 datalen = inlen - hash->confound_len - hash->hash_len;
2520 2519
2521 2520 /* Move just the decrypted input into place if necessary */
2522 2521 if (hash->confound_len > 0 || hash->hash_len > 0) {
2523 2522 if (tmi->dec_data.method == CRYPT_METHOD_DES3_CBC_SHA1)
2524 2523 mp->b_rptr += hash->confound_len;
2525 2524 else
2526 2525 mp->b_rptr += hash->confound_len + hash->hash_len;
2527 2526 }
2528 2527
2529 2528 ASSERT(mp->b_rptr + datalen <= DB_LIM(mp));
2530 2529 mp->b_wptr = mp->b_rptr + datalen;
2531 2530
2532 2531 return (mp);
2533 2532 }
2534 2533
2535 2534 static mblk_t *
2536 2535 do_decrypt(queue_t *q, mblk_t *mp)
2537 2536 {
2538 2537 struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr;
2539 2538 mblk_t *outmp;
2540 2539
2541 2540 switch (tmi->dec_data.method) {
2542 2541 case CRYPT_METHOD_DES_CFB:
2543 2542 outmp = des_cfb_decrypt(q, tmi, mp);
2544 2543 break;
2545 2544 case CRYPT_METHOD_NONE:
2546 2545 outmp = mp;
2547 2546 break;
2548 2547 case CRYPT_METHOD_DES_CBC_NULL:
2549 2548 outmp = des_cbc_decrypt(q, tmi, mp, &null_hash);
2550 2549 break;
2551 2550 case CRYPT_METHOD_DES_CBC_MD5:
2552 2551 outmp = des_cbc_decrypt(q, tmi, mp, &md5_hash);
2553 2552 break;
2554 2553 case CRYPT_METHOD_DES_CBC_CRC:
2555 2554 outmp = des_cbc_decrypt(q, tmi, mp, &crc32_hash);
2556 2555 break;
2557 2556 case CRYPT_METHOD_DES3_CBC_SHA1:
2558 2557 outmp = des_cbc_decrypt(q, tmi, mp, &sha1_hash);
2559 2558 break;
2560 2559 case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
2561 2560 case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP:
2562 2561 outmp = arcfour_hmac_md5_decrypt(q, tmi, mp, &md5_hash);
2563 2562 break;
2564 2563 case CRYPT_METHOD_AES128:
2565 2564 case CRYPT_METHOD_AES256:
2566 2565 outmp = aes_decrypt(q, tmi, mp, &sha1_hash);
2567 2566 break;
2568 2567 }
2569 2568 return (outmp);
2570 2569 }
2571 2570
2572 2571 /*
2573 2572 * do_encrypt
2574 2573 *
2575 2574 * Generic encryption routine for a single message block.
2576 2575 * The input mblk may be replaced by some encrypt routines
2577 2576 * because they add extra data in some cases that may exceed
2578 2577 * the input mblk_t size limit.
2579 2578 */
2580 2579 static mblk_t *
2581 2580 do_encrypt(queue_t *q, mblk_t *mp)
2582 2581 {
2583 2582 struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr;
2584 2583 mblk_t *outmp;
2585 2584
2586 2585 switch (tmi->enc_data.method) {
2587 2586 case CRYPT_METHOD_DES_CFB:
2588 2587 outmp = des_cfb_encrypt(q, tmi, mp);
2589 2588 break;
2590 2589 case CRYPT_METHOD_DES_CBC_NULL:
2591 2590 outmp = des_cbc_encrypt(q, tmi, mp, &null_hash);
2592 2591 break;
2593 2592 case CRYPT_METHOD_DES_CBC_MD5:
2594 2593 outmp = des_cbc_encrypt(q, tmi, mp, &md5_hash);
2595 2594 break;
2596 2595 case CRYPT_METHOD_DES_CBC_CRC:
2597 2596 outmp = des_cbc_encrypt(q, tmi, mp, &crc32_hash);
2598 2597 break;
2599 2598 case CRYPT_METHOD_DES3_CBC_SHA1:
2600 2599 outmp = des_cbc_encrypt(q, tmi, mp, &sha1_hash);
2601 2600 break;
2602 2601 case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
2603 2602 case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP:
2604 2603 outmp = arcfour_hmac_md5_encrypt(q, tmi, mp, &md5_hash);
2605 2604 break;
2606 2605 case CRYPT_METHOD_AES128:
2607 2606 case CRYPT_METHOD_AES256:
2608 2607 outmp = aes_encrypt(q, tmi, mp, &sha1_hash);
2609 2608 break;
2610 2609 case CRYPT_METHOD_NONE:
2611 2610 outmp = mp;
2612 2611 break;
2613 2612 }
2614 2613 return (outmp);
2615 2614 }
2616 2615
2617 2616 /*
2618 2617 * setup_crypto
2619 2618 *
2620 2619 * This takes the data from the CRYPTIOCSETUP ioctl
2621 2620 * and sets up a cipher_data_t structure for either
2622 2621 * encryption or decryption. This is where the
2623 2622 * key and initialization vector data get stored
2624 2623 * prior to beginning any crypto functions.
2625 2624 *
2626 2625 * Special note:
2627 2626 * Some applications(e.g. telnetd) have ability to switch
2628 2627 * crypto on/off periodically. Thus, the application may call
2629 2628 * the CRYPTIOCSETUP ioctl many times for the same stream.
2630 2629 * If the CRYPTIOCSETUP is called with 0 length key or ivec fields
2631 2630 * assume that the key, block, and saveblock fields that are already
2632 2631 * set from a previous CRIOCSETUP call are still valid. This helps avoid
2633 2632 * a rekeying error that could occur if we overwrite these fields
2634 2633 * with each CRYPTIOCSETUP call.
2635 2634 * In short, sometimes, CRYPTIOCSETUP is used to simply toggle on/off
2636 2635 * without resetting the original crypto parameters.
2637 2636 *
2638 2637 */
2639 2638 static int
2640 2639 setup_crypto(struct cr_info_t *ci, struct cipher_data_t *cd, int encrypt)
2641 2640 {
2642 2641 uint_t newblocklen;
2643 2642 uint32_t enc_usage = 0, dec_usage = 0;
2644 2643 int rv;
2645 2644
2646 2645 /*
2647 2646 * Initial sanity checks
2648 2647 */
2649 2648 if (!CR_METHOD_OK(ci->crypto_method)) {
2650 2649 cmn_err(CE_WARN, "Illegal crypto method (%d)",
2651 2650 ci->crypto_method);
2652 2651 return (EINVAL);
2653 2652 }
2654 2653 if (!CR_OPTIONS_OK(ci->option_mask)) {
2655 2654 cmn_err(CE_WARN, "Illegal crypto options (%d)",
2656 2655 ci->option_mask);
2657 2656 return (EINVAL);
2658 2657 }
2659 2658 if (!CR_IVUSAGE_OK(ci->ivec_usage)) {
2660 2659 cmn_err(CE_WARN, "Illegal ivec usage value (%d)",
2661 2660 ci->ivec_usage);
2662 2661 return (EINVAL);
2663 2662 }
2664 2663
2665 2664 cd->method = ci->crypto_method;
2666 2665 cd->bytes = 0;
2667 2666
2668 2667 if (ci->keylen > 0) {
2669 2668 if (cd->key != NULL) {
2670 2669 kmem_free(cd->key, cd->keylen);
2671 2670 cd->key = NULL;
2672 2671 cd->keylen = 0;
2673 2672 }
2674 2673 /*
2675 2674 * cd->key holds the copy of the raw key bytes passed in
2676 2675 * from the userland app.
2677 2676 */
2678 2677 cd->key = (char *)kmem_alloc((size_t)ci->keylen, KM_SLEEP);
2679 2678
2680 2679 cd->keylen = ci->keylen;
2681 2680 bcopy(ci->key, cd->key, (size_t)ci->keylen);
2682 2681 }
2683 2682
2684 2683 /*
2685 2684 * Configure the block size based on the type of cipher.
2686 2685 */
2687 2686 switch (cd->method) {
2688 2687 case CRYPT_METHOD_NONE:
2689 2688 newblocklen = 0;
2690 2689 break;
2691 2690 case CRYPT_METHOD_DES_CFB:
2692 2691 newblocklen = DEFAULT_DES_BLOCKLEN;
2693 2692 cd->mech_type = crypto_mech2id(SUN_CKM_DES_ECB);
2694 2693 break;
2695 2694 case CRYPT_METHOD_DES_CBC_NULL:
2696 2695 case CRYPT_METHOD_DES_CBC_MD5:
2697 2696 case CRYPT_METHOD_DES_CBC_CRC:
2698 2697 newblocklen = DEFAULT_DES_BLOCKLEN;
2699 2698 cd->mech_type = crypto_mech2id(SUN_CKM_DES_CBC);
2700 2699 break;
2701 2700 case CRYPT_METHOD_DES3_CBC_SHA1:
2702 2701 newblocklen = DEFAULT_DES_BLOCKLEN;
2703 2702 cd->mech_type = crypto_mech2id(SUN_CKM_DES3_CBC);
2704 2703 /* 3DES always uses the old usage constant */
2705 2704 enc_usage = RCMDV1_USAGE;
2706 2705 dec_usage = RCMDV1_USAGE;
2707 2706 break;
2708 2707 case CRYPT_METHOD_ARCFOUR_HMAC_MD5:
2709 2708 case CRYPT_METHOD_ARCFOUR_HMAC_MD5_EXP:
2710 2709 newblocklen = 0;
2711 2710 cd->mech_type = crypto_mech2id(SUN_CKM_RC4);
2712 2711 break;
2713 2712 case CRYPT_METHOD_AES128:
2714 2713 case CRYPT_METHOD_AES256:
2715 2714 newblocklen = DEFAULT_AES_BLOCKLEN;
2716 2715 cd->mech_type = crypto_mech2id(SUN_CKM_AES_ECB);
2717 2716 enc_usage = AES_ENCRYPT_USAGE;
2718 2717 dec_usage = AES_DECRYPT_USAGE;
2719 2718 break;
2720 2719 }
2721 2720 if (cd->mech_type == CRYPTO_MECH_INVALID) {
2722 2721 return (CRYPTO_FAILED);
2723 2722 }
2724 2723
2725 2724 /*
2726 2725 * If RC4, initialize the master crypto key used by
2727 2726 * the RC4 algorithm to derive the final encrypt and decrypt keys.
2728 2727 */
2729 2728 if (cd->keylen > 0 && IS_RC4_METHOD(cd->method)) {
2730 2729 /*
2731 2730 * cd->ckey is a kernel crypto key structure used as the
2732 2731 * master key in the RC4-HMAC crypto operations.
2733 2732 */
2734 2733 if (cd->ckey == NULL) {
2735 2734 cd->ckey = (crypto_key_t *)kmem_zalloc(
2736 2735 sizeof (crypto_key_t), KM_SLEEP);
2737 2736 }
2738 2737
2739 2738 cd->ckey->ck_format = CRYPTO_KEY_RAW;
2740 2739 cd->ckey->ck_data = cd->key;
2741 2740
2742 2741 /* key length for EF is measured in bits */
2743 2742 cd->ckey->ck_length = cd->keylen * 8;
2744 2743 }
2745 2744
2746 2745 /*
2747 2746 * cd->block and cd->saveblock are used as temporary storage for
2748 2747 * data that must be carried over between encrypt/decrypt operations
2749 2748 * in some of the "feedback" modes.
2750 2749 */
2751 2750 if (newblocklen != cd->blocklen) {
2752 2751 if (cd->block != NULL) {
2753 2752 kmem_free(cd->block, cd->blocklen);
2754 2753 cd->block = NULL;
2755 2754 }
2756 2755
2757 2756 if (cd->saveblock != NULL) {
2758 2757 kmem_free(cd->saveblock, cd->blocklen);
2759 2758 cd->saveblock = NULL;
2760 2759 }
2761 2760
2762 2761 cd->blocklen = newblocklen;
2763 2762 if (cd->blocklen) {
2764 2763 cd->block = (char *)kmem_zalloc((size_t)cd->blocklen,
2765 2764 KM_SLEEP);
2766 2765 }
2767 2766
2768 2767 if (cd->method == CRYPT_METHOD_DES_CFB)
2769 2768 cd->saveblock = (char *)kmem_zalloc(cd->blocklen,
2770 2769 KM_SLEEP);
2771 2770 else
2772 2771 cd->saveblock = NULL;
2773 2772 }
2774 2773
2775 2774 if (ci->iveclen != cd->ivlen) {
2776 2775 if (cd->ivec != NULL) {
2777 2776 kmem_free(cd->ivec, cd->ivlen);
2778 2777 cd->ivec = NULL;
2779 2778 }
2780 2779 if (ci->ivec_usage != IVEC_NEVER && ci->iveclen > 0) {
2781 2780 cd->ivec = (char *)kmem_zalloc((size_t)ci->iveclen,
2782 2781 KM_SLEEP);
2783 2782 cd->ivlen = ci->iveclen;
2784 2783 } else {
2785 2784 cd->ivlen = 0;
2786 2785 cd->ivec = NULL;
2787 2786 }
2788 2787 }
2789 2788 cd->option_mask = ci->option_mask;
2790 2789
2791 2790 /*
2792 2791 * Old protocol requires a static 'usage' value for
2793 2792 * deriving keys. Yuk.
2794 2793 */
2795 2794 if (cd->option_mask & CRYPTOPT_RCMD_MODE_V1) {
2796 2795 enc_usage = dec_usage = RCMDV1_USAGE;
2797 2796 }
2798 2797
2799 2798 if (cd->ivlen > cd->blocklen) {
2800 2799 cmn_err(CE_WARN, "setup_crypto: IV longer than block size");
2801 2800 return (EINVAL);
2802 2801 }
2803 2802
2804 2803 /*
2805 2804 * If we are using an IVEC "correctly" (i.e. set it once)
2806 2805 * copy it here.
2807 2806 */
2808 2807 if (ci->ivec_usage == IVEC_ONETIME && cd->block != NULL)
2809 2808 bcopy(ci->ivec, cd->block, (size_t)cd->ivlen);
2810 2809
2811 2810 cd->ivec_usage = ci->ivec_usage;
2812 2811 if (cd->ivec != NULL) {
2813 2812 /* Save the original IVEC in case we need it later */
2814 2813 bcopy(ci->ivec, cd->ivec, (size_t)cd->ivlen);
2815 2814 }
2816 2815 /*
2817 2816 * Special handling for 3DES-SHA1-HMAC and AES crypto:
2818 2817 * generate derived keys and context templates
2819 2818 * for better performance.
2820 2819 */
2821 2820 if (cd->method == CRYPT_METHOD_DES3_CBC_SHA1 ||
2822 2821 IS_AES_METHOD(cd->method)) {
2823 2822 crypto_mechanism_t enc_mech;
2824 2823 crypto_mechanism_t hmac_mech;
2825 2824
2826 2825 if (cd->d_encr_key.ck_data != NULL) {
2827 2826 bzero(cd->d_encr_key.ck_data, cd->keylen);
2828 2827 kmem_free(cd->d_encr_key.ck_data, cd->keylen);
2829 2828 }
2830 2829
2831 2830 if (cd->d_hmac_key.ck_data != NULL) {
2832 2831 bzero(cd->d_hmac_key.ck_data, cd->keylen);
2833 2832 kmem_free(cd->d_hmac_key.ck_data, cd->keylen);
2834 2833 }
2835 2834
2836 2835 if (cd->enc_tmpl != NULL)
2837 2836 (void) crypto_destroy_ctx_template(cd->enc_tmpl);
2838 2837
2839 2838 if (cd->hmac_tmpl != NULL)
2840 2839 (void) crypto_destroy_ctx_template(cd->hmac_tmpl);
2841 2840
2842 2841 enc_mech.cm_type = cd->mech_type;
2843 2842 enc_mech.cm_param = cd->ivec;
2844 2843 enc_mech.cm_param_len = cd->ivlen;
2845 2844
2846 2845 hmac_mech.cm_type = sha1_hmac_mech;
2847 2846 hmac_mech.cm_param = NULL;
2848 2847 hmac_mech.cm_param_len = 0;
2849 2848
2850 2849 /*
2851 2850 * Create the derived keys.
2852 2851 */
2853 2852 rv = create_derived_keys(cd,
2854 2853 (encrypt ? enc_usage : dec_usage),
2855 2854 &cd->d_encr_key, &cd->d_hmac_key);
2856 2855
2857 2856 if (rv != CRYPTO_SUCCESS) {
2858 2857 cmn_err(CE_WARN, "failed to create derived "
2859 2858 "keys: %0x", rv);
2860 2859 return (CRYPTO_FAILED);
2861 2860 }
2862 2861
2863 2862 rv = crypto_create_ctx_template(&enc_mech,
2864 2863 &cd->d_encr_key,
2865 2864 &cd->enc_tmpl, KM_SLEEP);
2866 2865 if (rv == CRYPTO_MECH_NOT_SUPPORTED) {
2867 2866 cd->enc_tmpl = NULL;
2868 2867 } else if (rv != CRYPTO_SUCCESS) {
2869 2868 cmn_err(CE_WARN, "failed to create enc template "
2870 2869 "for d_encr_key: %0x", rv);
2871 2870 return (CRYPTO_FAILED);
2872 2871 }
2873 2872
2874 2873 rv = crypto_create_ctx_template(&hmac_mech,
2875 2874 &cd->d_hmac_key,
2876 2875 &cd->hmac_tmpl, KM_SLEEP);
2877 2876 if (rv == CRYPTO_MECH_NOT_SUPPORTED) {
2878 2877 cd->hmac_tmpl = NULL;
2879 2878 } else if (rv != CRYPTO_SUCCESS) {
2880 2879 cmn_err(CE_WARN, "failed to create hmac template:"
2881 2880 " %0x", rv);
2882 2881 return (CRYPTO_FAILED);
2883 2882 }
2884 2883 } else if (IS_RC4_METHOD(cd->method)) {
2885 2884 bzero(&cd->d_encr_key, sizeof (crypto_key_t));
2886 2885 bzero(&cd->d_hmac_key, sizeof (crypto_key_t));
2887 2886 cd->ctx = NULL;
2888 2887 cd->enc_tmpl = NULL;
2889 2888 cd->hmac_tmpl = NULL;
2890 2889 }
2891 2890
2892 2891 /* Final sanity checks, make sure no fields are NULL */
2893 2892 if (cd->method != CRYPT_METHOD_NONE) {
2894 2893 if (cd->block == NULL && cd->blocklen > 0) {
2895 2894 #ifdef DEBUG
2896 2895 cmn_err(CE_WARN,
2897 2896 "setup_crypto: IV block not allocated");
2898 2897 #endif
2899 2898 return (ENOMEM);
2900 2899 }
2901 2900 if (cd->key == NULL && cd->keylen > 0) {
2902 2901 #ifdef DEBUG
2903 2902 cmn_err(CE_WARN,
2904 2903 "setup_crypto: key block not allocated");
2905 2904 #endif
2906 2905 return (ENOMEM);
2907 2906 }
2908 2907 if (cd->method == CRYPT_METHOD_DES_CFB &&
2909 2908 cd->saveblock == NULL && cd->blocklen > 0) {
2910 2909 #ifdef DEBUG
2911 2910 cmn_err(CE_WARN,
2912 2911 "setup_crypto: save block not allocated");
2913 2912 #endif
2914 2913 return (ENOMEM);
2915 2914 }
2916 2915 if (cd->ivec == NULL && cd->ivlen > 0) {
2917 2916 #ifdef DEBUG
2918 2917 cmn_err(CE_WARN,
2919 2918 "setup_crypto: IV not allocated");
2920 2919 #endif
2921 2920 return (ENOMEM);
2922 2921 }
2923 2922 }
2924 2923 return (0);
2925 2924 }
2926 2925
2927 2926 /*
2928 2927 * RCMDS require a 4 byte, clear text
2929 2928 * length field before each message.
2930 2929 * Add it now.
2931 2930 */
2932 2931 static mblk_t *
2933 2932 mklenmp(mblk_t *bp, uint32_t len)
2934 2933 {
2935 2934 mblk_t *lenmp;
2936 2935 uchar_t *ucp;
2937 2936
2938 2937 if (bp->b_rptr - 4 < DB_BASE(bp) || DB_REF(bp) > 1) {
2939 2938 lenmp = allocb(4, BPRI_MED);
2940 2939 if (lenmp != NULL) {
2941 2940 lenmp->b_rptr = lenmp->b_wptr = DB_LIM(lenmp);
2942 2941 linkb(lenmp, bp);
2943 2942 bp = lenmp;
2944 2943 }
2945 2944 }
2946 2945 ucp = bp->b_rptr;
2947 2946 *--ucp = len;
2948 2947 *--ucp = len >> 8;
2949 2948 *--ucp = len >> 16;
2950 2949 *--ucp = len >> 24;
2951 2950
2952 2951 bp->b_rptr = ucp;
2953 2952
2954 2953 return (bp);
2955 2954 }
2956 2955
2957 2956 static mblk_t *
2958 2957 encrypt_block(queue_t *q, struct tmodinfo *tmi, mblk_t *mp, size_t plainlen)
2959 2958 {
2960 2959 mblk_t *newmp;
2961 2960 size_t headspace;
2962 2961
2963 2962 mblk_t *cbp;
2964 2963 size_t cipherlen;
2965 2964 size_t extra = 0;
2966 2965 uint32_t ptlen = (uint32_t)plainlen;
2967 2966 /*
2968 2967 * If we are using the "NEW" RCMD mode,
2969 2968 * add 4 bytes to the plaintext for the
2970 2969 * plaintext length that gets prepended
2971 2970 * before encrypting.
2972 2971 */
2973 2972 if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2)
2974 2973 ptlen += 4;
2975 2974
2976 2975 cipherlen = encrypt_size(&tmi->enc_data, (size_t)ptlen);
2977 2976
2978 2977 /*
2979 2978 * if we must allocb, then make sure its enough
2980 2979 * to hold the length field so we dont have to allocb
2981 2980 * again down below in 'mklenmp'
2982 2981 */
2983 2982 if (ANY_RCMD_MODE(tmi->enc_data.option_mask)) {
2984 2983 extra = sizeof (uint32_t);
2985 2984 }
2986 2985
2987 2986 /*
2988 2987 * Calculate how much space is needed in front of
2989 2988 * the data.
2990 2989 */
2991 2990 headspace = plaintext_offset(&tmi->enc_data);
2992 2991
2993 2992 /*
2994 2993 * If the current block is too small, reallocate
2995 2994 * one large enough to hold the hdr, tail, and
2996 2995 * ciphertext.
2997 2996 */
2998 2997 if ((cipherlen + extra >= MBLKSIZE(mp)) || DB_REF(mp) > 1) {
2999 2998 int sz = P2ROUNDUP(cipherlen+extra, 8);
3000 2999
3001 3000 cbp = allocb_tmpl(sz, mp);
3002 3001 if (cbp == NULL) {
3003 3002 cmn_err(CE_WARN,
3004 3003 "allocb (%d bytes) failed", sz);
3005 3004 return (NULL);
3006 3005 }
3007 3006
3008 3007 cbp->b_cont = mp->b_cont;
3009 3008
3010 3009 /*
3011 3010 * headspace includes the length fields needed
3012 3011 * for the RCMD modes (v1 == 4 bytes, V2 = 8)
3013 3012 */
3014 3013 ASSERT(cbp->b_rptr + P2ROUNDUP(plainlen+headspace, 8)
3015 3014 <= DB_LIM(cbp));
3016 3015
3017 3016 cbp->b_rptr = DB_BASE(cbp) + headspace;
3018 3017 bcopy(mp->b_rptr, cbp->b_rptr, plainlen);
3019 3018 cbp->b_wptr = cbp->b_rptr + plainlen;
3020 3019
3021 3020 freeb(mp);
3022 3021 } else {
3023 3022 size_t extra = 0;
3024 3023 cbp = mp;
3025 3024
3026 3025 /*
3027 3026 * Some ciphers add HMAC after the final block
3028 3027 * of the ciphertext, not at the beginning like the
3029 3028 * 1-DES ciphers.
3030 3029 */
3031 3030 if (tmi->enc_data.method ==
3032 3031 CRYPT_METHOD_DES3_CBC_SHA1 ||
3033 3032 IS_AES_METHOD(tmi->enc_data.method)) {
3034 3033 extra = sha1_hash.hash_len;
3035 3034 }
3036 3035
3037 3036 /*
3038 3037 * Make sure the rptr is positioned correctly so that
3039 3038 * routines later do not have to shift this data around
3040 3039 */
3041 3040 if ((cbp->b_rptr + P2ROUNDUP(cipherlen + extra, 8) >
3042 3041 DB_LIM(cbp)) ||
3043 3042 (cbp->b_rptr - headspace < DB_BASE(cbp))) {
3044 3043 ovbcopy(cbp->b_rptr, DB_BASE(cbp) + headspace,
3045 3044 plainlen);
3046 3045 cbp->b_rptr = DB_BASE(cbp) + headspace;
3047 3046 cbp->b_wptr = cbp->b_rptr + plainlen;
3048 3047 }
3049 3048 }
3050 3049
3051 3050 ASSERT(cbp->b_rptr - headspace >= DB_BASE(cbp));
3052 3051 ASSERT(cbp->b_wptr <= DB_LIM(cbp));
3053 3052
3054 3053 /*
3055 3054 * If using RCMD_MODE_V2 (new rcmd mode), prepend
3056 3055 * the plaintext length before the actual plaintext.
3057 3056 */
3058 3057 if (tmi->enc_data.option_mask & CRYPTOPT_RCMD_MODE_V2) {
3059 3058 cbp->b_rptr -= RCMD_LEN_SZ;
3060 3059
3061 3060 /* put plaintext length at head of buffer */
3062 3061 *(cbp->b_rptr + 3) = (uchar_t)(plainlen & 0xff);
3063 3062 *(cbp->b_rptr + 2) = (uchar_t)((plainlen >> 8) & 0xff);
3064 3063 *(cbp->b_rptr + 1) = (uchar_t)((plainlen >> 16) & 0xff);
3065 3064 *(cbp->b_rptr) = (uchar_t)((plainlen >> 24) & 0xff);
3066 3065 }
3067 3066
3068 3067 newmp = do_encrypt(q, cbp);
3069 3068
3070 3069 if (newmp != NULL &&
3071 3070 (tmi->enc_data.option_mask &
3072 3071 (CRYPTOPT_RCMD_MODE_V1 | CRYPTOPT_RCMD_MODE_V2))) {
3073 3072 mblk_t *lp;
3074 3073 /*
3075 3074 * Add length field, required when this is
3076 3075 * used to encrypt "r*" commands(rlogin, rsh)
3077 3076 * with Kerberos.
3078 3077 */
3079 3078 lp = mklenmp(newmp, plainlen);
3080 3079
3081 3080 if (lp == NULL) {
3082 3081 freeb(newmp);
3083 3082 return (NULL);
3084 3083 } else {
3085 3084 newmp = lp;
3086 3085 }
3087 3086 }
3088 3087 return (newmp);
3089 3088 }
3090 3089
3091 3090 /*
3092 3091 * encrypt_msgb
3093 3092 *
3094 3093 * encrypt a single message. This routine adds the
3095 3094 * RCMD overhead bytes when necessary.
3096 3095 */
3097 3096 static mblk_t *
3098 3097 encrypt_msgb(queue_t *q, struct tmodinfo *tmi, mblk_t *mp)
3099 3098 {
3100 3099 size_t plainlen, outlen;
3101 3100 mblk_t *newmp = NULL;
3102 3101
3103 3102 /* If not encrypting, do nothing */
3104 3103 if (tmi->enc_data.method == CRYPT_METHOD_NONE) {
3105 3104 return (mp);
3106 3105 }
3107 3106
3108 3107 plainlen = MBLKL(mp);
3109 3108 if (plainlen == 0)
3110 3109 return (NULL);
3111 3110
3112 3111 /*
3113 3112 * If the block is too big, we encrypt in 4K chunks so that
3114 3113 * older rlogin clients do not choke on the larger buffers.
3115 3114 */
3116 3115 while ((plainlen = MBLKL(mp)) > MSGBUF_SIZE) {
3117 3116 mblk_t *mp1 = NULL;
3118 3117 outlen = MSGBUF_SIZE;
3119 3118 /*
3120 3119 * Allocate a new buffer that is only 4K bytes, the
3121 3120 * extra bytes are for crypto overhead.
3122 3121 */
3123 3122 mp1 = allocb(outlen + CONFOUNDER_BYTES, BPRI_MED);
3124 3123 if (mp1 == NULL) {
3125 3124 cmn_err(CE_WARN,
3126 3125 "allocb (%d bytes) failed",
3127 3126 (int)(outlen + CONFOUNDER_BYTES));
3128 3127 return (NULL);
3129 3128 }
3130 3129 /* Copy the next 4K bytes from the old block. */
3131 3130 bcopy(mp->b_rptr, mp1->b_rptr, outlen);
3132 3131 mp1->b_wptr = mp1->b_rptr + outlen;
3133 3132 /* Advance the old block. */
3134 3133 mp->b_rptr += outlen;
3135 3134
3136 3135 /* encrypt the new block */
3137 3136 newmp = encrypt_block(q, tmi, mp1, outlen);
3138 3137 if (newmp == NULL)
3139 3138 return (NULL);
3140 3139
3141 3140 putnext(q, newmp);
3142 3141 }
3143 3142 newmp = NULL;
3144 3143 /* If there is data left (< MSGBUF_SIZE), encrypt it. */
3145 3144 if ((plainlen = MBLKL(mp)) > 0)
3146 3145 newmp = encrypt_block(q, tmi, mp, plainlen);
3147 3146
3148 3147 return (newmp);
3149 3148 }
3150 3149
3151 3150 /*
3152 3151 * cryptmodwsrv
3153 3152 *
3154 3153 * Service routine for the write queue.
3155 3154 *
3156 3155 * Because data may be placed in the queue to hold between
3157 3156 * the CRYPTIOCSTOP and CRYPTIOCSTART ioctls, the service routine is needed.
3158 3157 */
3159 3158 static int
3160 3159 cryptmodwsrv(queue_t *q)
3161 3160 {
3162 3161 mblk_t *mp;
3163 3162 struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr;
3164 3163
3165 3164 while ((mp = getq(q)) != NULL) {
3166 3165 switch (mp->b_datap->db_type) {
3167 3166 default:
3168 3167 /*
3169 3168 * wput does not queue anything > QPCTL
3170 3169 */
3171 3170 if (!canputnext(q) ||
3172 3171 !(tmi->ready & CRYPT_WRITE_READY)) {
3173 3172 if (!putbq(q, mp)) {
3174 3173 freemsg(mp);
3175 3174 }
3176 3175 return (0);
3177 3176 }
3178 3177 putnext(q, mp);
3179 3178 break;
3180 3179 case M_DATA:
3181 3180 if (canputnext(q) && (tmi->ready & CRYPT_WRITE_READY)) {
3182 3181 mblk_t *bp;
3183 3182 mblk_t *newmsg = NULL;
3184 3183
3185 3184 /*
3186 3185 * If multiple msgs, concat into 1
3187 3186 * to minimize crypto operations later.
3188 3187 */
3189 3188 if (mp->b_cont != NULL) {
3190 3189 bp = msgpullup(mp, -1);
3191 3190 if (bp != NULL) {
3192 3191 freemsg(mp);
3193 3192 mp = bp;
3194 3193 }
3195 3194 }
3196 3195 newmsg = encrypt_msgb(q, tmi, mp);
3197 3196 if (newmsg != NULL)
3198 3197 putnext(q, newmsg);
3199 3198 } else {
3200 3199 if (!putbq(q, mp)) {
3201 3200 freemsg(mp);
3202 3201 }
3203 3202 return (0);
3204 3203 }
3205 3204 break;
3206 3205 }
3207 3206 }
3208 3207 return (0);
3209 3208 }
3210 3209
3211 3210 static void
3212 3211 start_stream(queue_t *wq, mblk_t *mp, uchar_t dir)
3213 3212 {
3214 3213 mblk_t *newmp = NULL;
3215 3214 struct tmodinfo *tmi = (struct tmodinfo *)wq->q_ptr;
3216 3215
3217 3216 if (dir == CRYPT_ENCRYPT) {
3218 3217 tmi->ready |= CRYPT_WRITE_READY;
3219 3218 (void) (STRLOG(CRYPTMOD_ID, 0, 5, SL_TRACE|SL_NOTE,
3220 3219 "start_stream: restart ENCRYPT/WRITE q"));
3221 3220
3222 3221 enableok(wq);
3223 3222 qenable(wq);
3224 3223 } else if (dir == CRYPT_DECRYPT) {
3225 3224 /*
3226 3225 * put any extra data in the RD
3227 3226 * queue to be processed and
3228 3227 * sent back up.
3229 3228 */
3230 3229 newmp = mp->b_cont;
3231 3230 mp->b_cont = NULL;
3232 3231
3233 3232 tmi->ready |= CRYPT_READ_READY;
3234 3233 (void) (STRLOG(CRYPTMOD_ID, 0, 5,
3235 3234 SL_TRACE|SL_NOTE,
3236 3235 "start_stream: restart "
3237 3236 "DECRYPT/READ q"));
3238 3237
3239 3238 if (newmp != NULL)
3240 3239 if (!putbq(RD(wq), newmp))
3241 3240 freemsg(newmp);
3242 3241
3243 3242 enableok(RD(wq));
3244 3243 qenable(RD(wq));
3245 3244 }
3246 3245
3247 3246 miocack(wq, mp, 0, 0);
3248 3247 }
3249 3248
3250 3249 /*
3251 3250 * Write-side put procedure. Its main task is to detect ioctls and
3252 3251 * FLUSH operations. Other message types are passed on through.
3253 3252 */
3254 3253 static void
3255 3254 cryptmodwput(queue_t *wq, mblk_t *mp)
3256 3255 {
3257 3256 struct iocblk *iocp;
3258 3257 struct tmodinfo *tmi = (struct tmodinfo *)wq->q_ptr;
3259 3258 int ret, err;
3260 3259
3261 3260 switch (mp->b_datap->db_type) {
3262 3261 case M_DATA:
3263 3262 if (wq->q_first == NULL && canputnext(wq) &&
3264 3263 (tmi->ready & CRYPT_WRITE_READY) &&
3265 3264 tmi->enc_data.method == CRYPT_METHOD_NONE) {
3266 3265 putnext(wq, mp);
3267 3266 return;
3268 3267 }
3269 3268 /* else, put it in the service queue */
3270 3269 if (!putq(wq, mp)) {
3271 3270 freemsg(mp);
3272 3271 }
3273 3272 break;
3274 3273 case M_FLUSH:
3275 3274 if (*mp->b_rptr & FLUSHW) {
3276 3275 flushq(wq, FLUSHDATA);
3277 3276 }
3278 3277 putnext(wq, mp);
3279 3278 break;
3280 3279 case M_IOCTL:
3281 3280 iocp = (struct iocblk *)mp->b_rptr;
3282 3281 switch (iocp->ioc_cmd) {
3283 3282 case CRYPTIOCSETUP:
3284 3283 ret = 0;
3285 3284 (void) (STRLOG(CRYPTMOD_ID, 0, 5,
3286 3285 SL_TRACE | SL_NOTE,
3287 3286 "wput: got CRYPTIOCSETUP "
3288 3287 "ioctl(%d)", iocp->ioc_cmd));
3289 3288
3290 3289 if ((err = miocpullup(mp,
3291 3290 sizeof (struct cr_info_t))) != 0) {
3292 3291 cmn_err(CE_WARN,
3293 3292 "wput: miocpullup failed for cr_info_t");
3294 3293 miocnak(wq, mp, 0, err);
3295 3294 } else {
3296 3295 struct cr_info_t *ci;
3297 3296 ci = (struct cr_info_t *)mp->b_cont->b_rptr;
3298 3297
3299 3298 if (ci->direction_mask & CRYPT_ENCRYPT) {
3300 3299 ret = setup_crypto(ci, &tmi->enc_data, 1);
3301 3300 }
3302 3301
3303 3302 if (ret == 0 &&
3304 3303 (ci->direction_mask & CRYPT_DECRYPT)) {
3305 3304 ret = setup_crypto(ci, &tmi->dec_data, 0);
3306 3305 }
3307 3306 if (ret == 0 &&
3308 3307 (ci->direction_mask & CRYPT_DECRYPT) &&
3309 3308 ANY_RCMD_MODE(tmi->dec_data.option_mask)) {
3310 3309 bzero(&tmi->rcmd_state,
3311 3310 sizeof (tmi->rcmd_state));
3312 3311 }
3313 3312 if (ret == 0) {
3314 3313 miocack(wq, mp, 0, 0);
3315 3314 } else {
3316 3315 cmn_err(CE_WARN,
3317 3316 "wput: setup_crypto failed");
3318 3317 miocnak(wq, mp, 0, ret);
3319 3318 }
3320 3319 (void) (STRLOG(CRYPTMOD_ID, 0, 5,
3321 3320 SL_TRACE|SL_NOTE,
3322 3321 "wput: done with SETUP "
3323 3322 "ioctl"));
3324 3323 }
3325 3324 break;
3326 3325 case CRYPTIOCSTOP:
3327 3326 (void) (STRLOG(CRYPTMOD_ID, 0, 5,
3328 3327 SL_TRACE|SL_NOTE,
3329 3328 "wput: got CRYPTIOCSTOP "
3330 3329 "ioctl(%d)", iocp->ioc_cmd));
3331 3330
3332 3331 if ((err = miocpullup(mp, sizeof (uint32_t))) != 0) {
3333 3332 cmn_err(CE_WARN,
3334 3333 "wput: CRYPTIOCSTOP ioctl wrong "
3335 3334 "size (%d should be %d)",
3336 3335 (int)iocp->ioc_count,
3337 3336 (int)sizeof (uint32_t));
3338 3337 miocnak(wq, mp, 0, err);
3339 3338 } else {
3340 3339 uint32_t *stopdir;
3341 3340
3342 3341 stopdir = (uint32_t *)mp->b_cont->b_rptr;
3343 3342 if (!CR_DIRECTION_OK(*stopdir)) {
3344 3343 miocnak(wq, mp, 0, EINVAL);
3345 3344 return;
3346 3345 }
3347 3346
3348 3347 /* disable the queues until further notice */
3349 3348 if (*stopdir & CRYPT_ENCRYPT) {
3350 3349 noenable(wq);
3351 3350 tmi->ready &= ~CRYPT_WRITE_READY;
3352 3351 }
3353 3352 if (*stopdir & CRYPT_DECRYPT) {
3354 3353 noenable(RD(wq));
3355 3354 tmi->ready &= ~CRYPT_READ_READY;
3356 3355 }
3357 3356
3358 3357 miocack(wq, mp, 0, 0);
3359 3358 }
3360 3359 break;
3361 3360 case CRYPTIOCSTARTDEC:
3362 3361 (void) (STRLOG(CRYPTMOD_ID, 0, 5,
3363 3362 SL_TRACE|SL_NOTE,
3364 3363 "wput: got CRYPTIOCSTARTDEC "
3365 3364 "ioctl(%d)", iocp->ioc_cmd));
3366 3365
3367 3366 start_stream(wq, mp, CRYPT_DECRYPT);
3368 3367 break;
3369 3368 case CRYPTIOCSTARTENC:
3370 3369 (void) (STRLOG(CRYPTMOD_ID, 0, 5,
3371 3370 SL_TRACE|SL_NOTE,
3372 3371 "wput: got CRYPTIOCSTARTENC "
3373 3372 "ioctl(%d)", iocp->ioc_cmd));
3374 3373
3375 3374 start_stream(wq, mp, CRYPT_ENCRYPT);
3376 3375 break;
3377 3376 default:
3378 3377 putnext(wq, mp);
3379 3378 break;
3380 3379 }
3381 3380 break;
3382 3381 default:
3383 3382 if (queclass(mp) < QPCTL) {
3384 3383 if (wq->q_first != NULL || !canputnext(wq)) {
3385 3384 if (!putq(wq, mp))
3386 3385 freemsg(mp);
3387 3386 return;
3388 3387 }
3389 3388 }
3390 3389 putnext(wq, mp);
3391 3390 break;
3392 3391 }
3393 3392 }
3394 3393
3395 3394 /*
3396 3395 * decrypt_rcmd_mblks
3397 3396 *
3398 3397 * Because kerberized r* commands(rsh, rlogin, etc)
3399 3398 * use a 4 byte length field to indicate the # of
3400 3399 * PLAINTEXT bytes that are encrypted in the field
3401 3400 * that follows, we must parse out each message and
3402 3401 * break out the length fields prior to sending them
3403 3402 * upstream to our Solaris r* clients/servers which do
3404 3403 * NOT understand this format.
3405 3404 *
3406 3405 * Kerberized/encrypted message format:
3407 3406 * -------------------------------
3408 3407 * | XXXX | N bytes of ciphertext|
3409 3408 * -------------------------------
3410 3409 *
3411 3410 * Where: XXXX = number of plaintext bytes that were encrypted in
3412 3411 * to make the ciphertext field. This is done
3413 3412 * because we are using a cipher that pads out to
3414 3413 * an 8 byte boundary. We only want the application
3415 3414 * layer to see the correct number of plain text bytes,
3416 3415 * not plaintext + pad. So, after we decrypt, we
3417 3416 * must trim the output block down to the intended
3418 3417 * plaintext length and eliminate the pad bytes.
3419 3418 *
3420 3419 * This routine takes the entire input message, breaks it into
3421 3420 * a new message that does not contain these length fields and
3422 3421 * returns a message consisting of mblks filled with just ciphertext.
3423 3422 *
3424 3423 */
3425 3424 static mblk_t *
3426 3425 decrypt_rcmd_mblks(queue_t *q, mblk_t *mp)
3427 3426 {
3428 3427 mblk_t *newmp = NULL;
3429 3428 size_t msglen;
3430 3429 struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr;
3431 3430
3432 3431 msglen = msgsize(mp);
3433 3432
3434 3433 /*
3435 3434 * If we need the length field, get it here.
3436 3435 * Test the "plaintext length" indicator.
3437 3436 */
3438 3437 if (tmi->rcmd_state.pt_len == 0) {
3439 3438 uint32_t elen;
3440 3439 int tocopy;
3441 3440 mblk_t *nextp;
3442 3441
3443 3442 /*
3444 3443 * Make sure we have recieved all 4 bytes of the
3445 3444 * length field.
3446 3445 */
3447 3446 while (mp != NULL) {
3448 3447 ASSERT(tmi->rcmd_state.cd_len < sizeof (uint32_t));
3449 3448
3450 3449 tocopy = sizeof (uint32_t) -
3451 3450 tmi->rcmd_state.cd_len;
3452 3451 if (tocopy > msglen)
3453 3452 tocopy = msglen;
3454 3453
3455 3454 ASSERT(mp->b_rptr + tocopy <= DB_LIM(mp));
3456 3455 bcopy(mp->b_rptr,
3457 3456 (char *)(&tmi->rcmd_state.next_len +
3458 3457 tmi->rcmd_state.cd_len), tocopy);
3459 3458
3460 3459 tmi->rcmd_state.cd_len += tocopy;
3461 3460
3462 3461 if (tmi->rcmd_state.cd_len >= sizeof (uint32_t)) {
3463 3462 tmi->rcmd_state.next_len =
3464 3463 ntohl(tmi->rcmd_state.next_len);
3465 3464 break;
3466 3465 }
3467 3466
3468 3467 nextp = mp->b_cont;
3469 3468 mp->b_cont = NULL;
3470 3469 freeb(mp);
3471 3470 mp = nextp;
3472 3471 }
3473 3472
3474 3473 if (mp == NULL) {
3475 3474 return (NULL);
3476 3475 }
3477 3476 /*
3478 3477 * recalculate the msglen now that we've read the
3479 3478 * length and adjusted the bufptr (b_rptr).
3480 3479 */
3481 3480 msglen -= tocopy;
3482 3481 mp->b_rptr += tocopy;
3483 3482
3484 3483 tmi->rcmd_state.pt_len = tmi->rcmd_state.next_len;
3485 3484
3486 3485 if (tmi->rcmd_state.pt_len <= 0) {
3487 3486 /*
3488 3487 * Return an IO error to break the connection. there
3489 3488 * is no way to recover from this. Usually it means
3490 3489 * the app has incorrectly requested decryption on
3491 3490 * a non-encrypted stream, thus the "pt_len" field
3492 3491 * is negative.
3493 3492 */
3494 3493 mp->b_datap->db_type = M_ERROR;
3495 3494 mp->b_rptr = mp->b_datap->db_base;
3496 3495 *mp->b_rptr = EIO;
3497 3496 mp->b_wptr = mp->b_rptr + sizeof (char);
3498 3497
3499 3498 freemsg(mp->b_cont);
3500 3499 mp->b_cont = NULL;
3501 3500 qreply(WR(q), mp);
3502 3501 tmi->rcmd_state.cd_len = tmi->rcmd_state.pt_len = 0;
3503 3502 return (NULL);
3504 3503 }
3505 3504
3506 3505 /*
3507 3506 * If this is V2 mode, then the encrypted data is actually
3508 3507 * 4 bytes bigger than the indicated len because the plaintext
3509 3508 * length is encrypted for an additional security check, but
3510 3509 * its not counted as part of the overall length we just read.
3511 3510 * Strange and confusing, but true.
3512 3511 */
3513 3512
3514 3513 if (tmi->dec_data.option_mask & CRYPTOPT_RCMD_MODE_V2)
3515 3514 elen = tmi->rcmd_state.pt_len + 4;
3516 3515 else
3517 3516 elen = tmi->rcmd_state.pt_len;
3518 3517
3519 3518 tmi->rcmd_state.cd_len = encrypt_size(&tmi->dec_data, elen);
3520 3519
3521 3520 /*
3522 3521 * Allocate an mblk to hold the cipher text until it is
3523 3522 * all ready to be processed.
3524 3523 */
3525 3524 tmi->rcmd_state.c_msg = allocb(tmi->rcmd_state.cd_len,
3526 3525 BPRI_HI);
3527 3526 if (tmi->rcmd_state.c_msg == NULL) {
3528 3527 #ifdef DEBUG
3529 3528 cmn_err(CE_WARN, "decrypt_rcmd_msgb: allocb failed "
3530 3529 "for %d bytes",
3531 3530 (int)tmi->rcmd_state.cd_len);
3532 3531 #endif
3533 3532 /*
3534 3533 * Return an IO error to break the connection.
3535 3534 */
3536 3535 mp->b_datap->db_type = M_ERROR;
3537 3536 mp->b_rptr = mp->b_datap->db_base;
3538 3537 *mp->b_rptr = EIO;
3539 3538 mp->b_wptr = mp->b_rptr + sizeof (char);
3540 3539 freemsg(mp->b_cont);
3541 3540 mp->b_cont = NULL;
3542 3541 tmi->rcmd_state.cd_len = tmi->rcmd_state.pt_len = 0;
3543 3542 qreply(WR(q), mp);
3544 3543 return (NULL);
3545 3544 }
3546 3545 }
3547 3546
3548 3547 /*
3549 3548 * If this entire message was just the length field,
3550 3549 * free and return. The actual data will probably be next.
3551 3550 */
3552 3551 if (msglen == 0) {
3553 3552 freemsg(mp);
3554 3553 return (NULL);
3555 3554 }
3556 3555
3557 3556 /*
3558 3557 * Copy as much of the cipher text as possible into
3559 3558 * the new msgb (c_msg).
3560 3559 *
3561 3560 * Logic: if we got some bytes (msglen) and we still
3562 3561 * "need" some bytes (len-rcvd), get them here.
3563 3562 */
3564 3563 ASSERT(tmi->rcmd_state.c_msg != NULL);
3565 3564 if (msglen > 0 &&
3566 3565 (tmi->rcmd_state.cd_len > MBLKL(tmi->rcmd_state.c_msg))) {
3567 3566 mblk_t *bp, *nextp;
3568 3567 size_t n;
3569 3568
3570 3569 /*
3571 3570 * Walk the mblks and copy just as many bytes as we need
3572 3571 * for this particular block of cipher text.
3573 3572 */
3574 3573 bp = mp;
3575 3574 while (bp != NULL) {
3576 3575 size_t needed;
3577 3576 size_t tocopy;
3578 3577 n = MBLKL(bp);
3579 3578
3580 3579 needed = tmi->rcmd_state.cd_len -
3581 3580 MBLKL(tmi->rcmd_state.c_msg);
3582 3581
3583 3582 tocopy = (needed >= n ? n : needed);
3584 3583
3585 3584 ASSERT(bp->b_rptr + tocopy <= DB_LIM(bp));
3586 3585 ASSERT(tmi->rcmd_state.c_msg->b_wptr + tocopy <=
3587 3586 DB_LIM(tmi->rcmd_state.c_msg));
3588 3587
3589 3588 /* Copy to end of new mblk */
3590 3589 bcopy(bp->b_rptr, tmi->rcmd_state.c_msg->b_wptr,
3591 3590 tocopy);
3592 3591
3593 3592 tmi->rcmd_state.c_msg->b_wptr += tocopy;
3594 3593
3595 3594 bp->b_rptr += tocopy;
3596 3595
3597 3596 nextp = bp->b_cont;
3598 3597
3599 3598 /*
3600 3599 * If we used this whole block, free it and
3601 3600 * move on.
3602 3601 */
3603 3602 if (!MBLKL(bp)) {
3604 3603 freeb(bp);
3605 3604 bp = NULL;
3606 3605 }
3607 3606
3608 3607 /* If we got what we needed, stop the loop */
3609 3608 if (MBLKL(tmi->rcmd_state.c_msg) ==
3610 3609 tmi->rcmd_state.cd_len) {
3611 3610 /*
3612 3611 * If there is more data in the message,
3613 3612 * its for another block of cipher text,
3614 3613 * put it back in the queue for next time.
3615 3614 */
3616 3615 if (bp) {
3617 3616 if (!putbq(q, bp))
3618 3617 freemsg(bp);
3619 3618 } else if (nextp != NULL) {
3620 3619 /*
3621 3620 * If there is more, put it back in the
3622 3621 * queue for another pass thru.
3623 3622 */
3624 3623 if (!putbq(q, nextp))
3625 3624 freemsg(nextp);
3626 3625 }
3627 3626 break;
3628 3627 }
3629 3628 bp = nextp;
3630 3629 }
3631 3630 }
3632 3631 /*
3633 3632 * Finally, if we received all the cipher text data for
3634 3633 * this message, decrypt it into a new msg and send it up
3635 3634 * to the app.
3636 3635 */
3637 3636 if (tmi->rcmd_state.pt_len > 0 &&
3638 3637 MBLKL(tmi->rcmd_state.c_msg) == tmi->rcmd_state.cd_len) {
3639 3638 mblk_t *bp;
3640 3639 mblk_t *newbp;
3641 3640
3642 3641 /*
3643 3642 * Now we can use our msg that we created when the
3644 3643 * initial message boundary was detected.
3645 3644 */
3646 3645 bp = tmi->rcmd_state.c_msg;
3647 3646 tmi->rcmd_state.c_msg = NULL;
3648 3647
3649 3648 newbp = do_decrypt(q, bp);
3650 3649 if (newbp != NULL) {
3651 3650 bp = newbp;
3652 3651 /*
3653 3652 * If using RCMD_MODE_V2 ("new" mode),
3654 3653 * look at the 4 byte plaintext length that
3655 3654 * was just decrypted and compare with the
3656 3655 * original pt_len value that was received.
3657 3656 */
3658 3657 if (tmi->dec_data.option_mask &
3659 3658 CRYPTOPT_RCMD_MODE_V2) {
3660 3659 uint32_t pt_len2;
3661 3660
3662 3661 pt_len2 = *(uint32_t *)bp->b_rptr;
3663 3662 pt_len2 = ntohl(pt_len2);
3664 3663 /*
3665 3664 * Make sure the 2 pt len fields agree.
3666 3665 */
3667 3666 if (pt_len2 != tmi->rcmd_state.pt_len) {
3668 3667 cmn_err(CE_WARN,
3669 3668 "Inconsistent length fields"
3670 3669 " received %d != %d",
3671 3670 (int)tmi->rcmd_state.pt_len,
3672 3671 (int)pt_len2);
3673 3672 bp->b_datap->db_type = M_ERROR;
3674 3673 bp->b_rptr = bp->b_datap->db_base;
3675 3674 *bp->b_rptr = EIO;
3676 3675 bp->b_wptr = bp->b_rptr + sizeof (char);
3677 3676 freemsg(bp->b_cont);
3678 3677 bp->b_cont = NULL;
3679 3678 tmi->rcmd_state.cd_len = 0;
3680 3679 qreply(WR(q), bp);
3681 3680 return (NULL);
3682 3681 }
3683 3682 bp->b_rptr += sizeof (uint32_t);
3684 3683 }
3685 3684
3686 3685 /*
3687 3686 * Trim the decrypted block the length originally
3688 3687 * indicated by the sender. This is to remove any
3689 3688 * padding bytes that the sender added to satisfy
3690 3689 * requirements of the crypto algorithm.
3691 3690 */
3692 3691 bp->b_wptr = bp->b_rptr + tmi->rcmd_state.pt_len;
3693 3692
3694 3693 newmp = bp;
3695 3694
3696 3695 /*
3697 3696 * Reset our state to indicate we are ready
3698 3697 * for a new message.
3699 3698 */
3700 3699 tmi->rcmd_state.pt_len = 0;
3701 3700 tmi->rcmd_state.cd_len = 0;
3702 3701 } else {
3703 3702 #ifdef DEBUG
3704 3703 cmn_err(CE_WARN,
3705 3704 "decrypt_rcmd: do_decrypt on %d bytes failed",
3706 3705 (int)tmi->rcmd_state.cd_len);
3707 3706 #endif
3708 3707 /*
3709 3708 * do_decrypt already handled failures, just
3710 3709 * return NULL.
3711 3710 */
3712 3711 tmi->rcmd_state.pt_len = 0;
3713 3712 tmi->rcmd_state.cd_len = 0;
3714 3713 return (NULL);
3715 3714 }
3716 3715 }
3717 3716
3718 3717 /*
3719 3718 * return the new message with the 'length' fields removed
3720 3719 */
3721 3720 return (newmp);
3722 3721 }
3723 3722
3724 3723 /*
3725 3724 * cryptmodrsrv
3726 3725 *
3727 3726 * Read queue service routine
3728 3727 * Necessary because if the ready flag is not set
3729 3728 * (via CRYPTIOCSTOP/CRYPTIOCSTART ioctls) then the data
3730 3729 * must remain on queue and not be passed along.
3731 3730 */
3732 3731 static int
3733 3732 cryptmodrsrv(queue_t *q)
3734 3733 {
3735 3734 mblk_t *mp, *bp;
3736 3735 struct tmodinfo *tmi = (struct tmodinfo *)q->q_ptr;
3737 3736
3738 3737 while ((mp = getq(q)) != NULL) {
3739 3738 switch (mp->b_datap->db_type) {
3740 3739 case M_DATA:
3741 3740 if (canputnext(q) && tmi->ready & CRYPT_READ_READY) {
3742 3741 /*
3743 3742 * Process "rcmd" messages differently because
3744 3743 * they contain a 4 byte plaintext length
3745 3744 * id that needs to be removed.
3746 3745 */
3747 3746 if (tmi->dec_data.method != CRYPT_METHOD_NONE &&
3748 3747 (tmi->dec_data.option_mask &
3749 3748 (CRYPTOPT_RCMD_MODE_V1 |
3750 3749 CRYPTOPT_RCMD_MODE_V2))) {
3751 3750 mp = decrypt_rcmd_mblks(q, mp);
3752 3751 if (mp)
3753 3752 putnext(q, mp);
3754 3753 continue;
3755 3754 }
3756 3755 if ((bp = msgpullup(mp, -1)) != NULL) {
3757 3756 freemsg(mp);
3758 3757 if (MBLKL(bp) > 0) {
3759 3758 mp = do_decrypt(q, bp);
3760 3759 if (mp != NULL)
3761 3760 putnext(q, mp);
3762 3761 }
3763 3762 }
3764 3763 } else {
3765 3764 if (!putbq(q, mp)) {
3766 3765 freemsg(mp);
3767 3766 }
3768 3767 return (0);
3769 3768 }
3770 3769 break;
3771 3770 default:
3772 3771 /*
3773 3772 * rput does not queue anything > QPCTL, so we don't
3774 3773 * need to check for it here.
3775 3774 */
3776 3775 if (!canputnext(q)) {
3777 3776 if (!putbq(q, mp))
3778 3777 freemsg(mp);
3779 3778 return (0);
3780 3779 }
3781 3780 putnext(q, mp);
3782 3781 break;
3783 3782 }
3784 3783 }
3785 3784 return (0);
3786 3785 }
3787 3786
3788 3787
3789 3788 /*
3790 3789 * Read-side put procedure.
3791 3790 */
3792 3791 static void
3793 3792 cryptmodrput(queue_t *rq, mblk_t *mp)
3794 3793 {
3795 3794 switch (mp->b_datap->db_type) {
3796 3795 case M_DATA:
3797 3796 if (!putq(rq, mp)) {
3798 3797 freemsg(mp);
3799 3798 }
3800 3799 break;
3801 3800 case M_FLUSH:
3802 3801 if (*mp->b_rptr & FLUSHR) {
3803 3802 flushq(rq, FLUSHALL);
3804 3803 }
3805 3804 putnext(rq, mp);
3806 3805 break;
3807 3806 default:
3808 3807 if (queclass(mp) < QPCTL) {
3809 3808 if (rq->q_first != NULL || !canputnext(rq)) {
3810 3809 if (!putq(rq, mp))
3811 3810 freemsg(mp);
3812 3811 return;
3813 3812 }
3814 3813 }
3815 3814 putnext(rq, mp);
3816 3815 break;
3817 3816 }
3818 3817 }
↓ open down ↓ |
3624 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX