Print this page
first pass
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnsl/key/xcrypt.c
+++ new/usr/src/lib/libnsl/key/xcrypt.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22
23 23 /*
24 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 25 * Use is subject to license terms.
26 26 */
27 27
28 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 29 /* All Rights Reserved */
30 30
31 31 /*
32 32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 33 * under license from the Regents of the University of California.
34 34 */
35 35
36 36 #pragma ident "%Z%%M% %I% %E% SMI"
37 37
38 38 /*
39 39 * Hex encryption/decryption and utility routines
40 40 */
41 41
42 42 #include "mt.h"
43 43 #include <stdio.h>
44 44 #include <stdlib.h>
45 45 #include <sys/types.h>
46 46 #include <rpc/rpc.h>
47 47 #include <rpc/key_prot.h> /* for KEYCHECKSUMSIZE */
48 48 #include <rpc/des_crypt.h>
49 49 #include <string.h>
50 50 #include <rpcsvc/nis_dhext.h>
51 51 #include <md5.h>
52 52
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
53 53 #define MD5HEXSIZE 32
54 54
55 55 extern int bin2hex(int len, unsigned char *binnum, char *hexnum);
56 56 extern int hex2bin(int len, char *hexnum, char *binnum);
57 57 static char hex[]; /* forward */
58 58 static char hexval();
59 59
60 60 int passwd2des(char *, char *);
61 61 static int weak_DES_key(des_block);
62 62
63 -/* EXPORT DELETE START */
64 63 /*
65 64 * For export control reasons, we want to limit the maximum size of
66 65 * data that can be encrypted or decrypted. We limit this to 1024
67 66 * bits of key data, which amounts to 128 bytes.
68 67 *
69 68 * For the extended DH project, we have increased it to
70 69 * 144 bytes (128key + 16checksum) to accomadate all the 128 bytes
71 70 * being used by the new 1024bit keys plus 16 bytes MD5 checksum.
72 71 * We discussed this with Sun's export control office and lawyers
73 72 * and we have reason to believe this is ok for export.
74 73 */
75 74 #define MAX_KEY_CRYPT_LEN 144
76 -/* EXPORT DELETE END */
77 75
78 76 /*
79 77 * Encrypt a secret key given passwd
80 78 * The secret key is passed and returned in hex notation.
81 79 * Its length must be a multiple of 16 hex digits (64 bits).
82 80 */
83 81 int
84 82 xencrypt(secret, passwd)
85 83 char *secret;
86 84 char *passwd;
87 85 {
88 -/* EXPORT DELETE START */
89 86 char key[8];
90 87 char ivec[8];
91 88 char *buf;
92 89 int err;
93 90 int len;
94 91
95 92 len = (int)strlen(secret) / 2;
96 93 if (len > MAX_KEY_CRYPT_LEN)
97 94 return (0);
98 95 buf = malloc((unsigned)len);
99 96 (void) hex2bin(len, secret, buf);
100 97 (void) passwd2des(passwd, key);
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
101 98 (void) memset(ivec, 0, 8);
102 99
103 100 err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
104 101 if (DES_FAILED(err)) {
105 102 free(buf);
106 103 return (0);
107 104 }
108 105 (void) bin2hex(len, (unsigned char *) buf, secret);
109 106 free(buf);
110 107 return (1);
111 -#if 0
112 -/* EXPORT DELETE END */
113 - return (0);
114 -/* EXPORT DELETE START */
115 -#endif
116 -/* EXPORT DELETE END */
117 108 }
118 109
119 110 /*
120 111 * Decrypt secret key using passwd
121 112 * The secret key is passed and returned in hex notation.
122 113 * Once again, the length is a multiple of 16 hex digits
123 114 */
124 115 int
125 116 xdecrypt(secret, passwd)
126 117 char *secret;
127 118 char *passwd;
128 119 {
129 -/* EXPORT DELETE START */
130 120 char key[8];
131 121 char ivec[8];
132 122 char *buf;
133 123 int err;
134 124 int len;
135 125
136 126 len = (int)strlen(secret) / 2;
137 127 if (len > MAX_KEY_CRYPT_LEN)
138 128 return (0);
139 129 buf = malloc((unsigned)len);
140 130
141 131 (void) hex2bin(len, secret, buf);
142 132 (void) passwd2des(passwd, key);
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
143 133 (void) memset(ivec, 0, 8);
144 134
145 135 err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
146 136 if (DES_FAILED(err)) {
147 137 free(buf);
148 138 return (0);
149 139 }
150 140 (void) bin2hex(len, (unsigned char *) buf, secret);
151 141 free(buf);
152 142 return (1);
153 -#if 0
154 -/* EXPORT DELETE END */
155 - return (0);
156 -/* EXPORT DELETE START */
157 -#endif
158 -/* EXPORT DELETE END */
159 143 }
160 144
161 145 /*
162 146 * Turn password into DES key
163 147 */
164 148 int
165 149 passwd2des(pw, key)
166 150 char *pw;
167 151 char *key;
168 152 {
169 153 int i;
170 154
171 155 (void) memset(key, 0, 8);
172 156 for (i = 0; *pw; i = (i+1) % 8) {
173 157 key[i] ^= *pw++ << 1;
174 158 }
175 159 des_setparity(key);
176 160 return (1);
177 161 }
178 162
179 163
180 164 /*
181 165 * Hex to binary conversion
182 166 */
183 167 int
184 168 hex2bin(len, hexnum, binnum)
185 169 int len;
186 170 char *hexnum;
187 171 char *binnum;
188 172 {
189 173 int i;
190 174
191 175 for (i = 0; i < len; i++) {
192 176 *binnum++ = 16 * hexval(hexnum[2 * i]) +
193 177 hexval(hexnum[2 * i + 1]);
194 178 }
195 179 return (1);
196 180 }
197 181
198 182 /*
199 183 * Binary to hex conversion
200 184 */
201 185 int
202 186 bin2hex(len, binnum, hexnum)
203 187 int len;
204 188 unsigned char *binnum;
205 189 char *hexnum;
206 190 {
207 191 int i;
208 192 unsigned val;
209 193
210 194 for (i = 0; i < len; i++) {
211 195 val = binnum[i];
212 196 hexnum[i*2] = hex[val >> 4];
213 197 hexnum[i*2+1] = hex[val & 0xf];
214 198 }
215 199 hexnum[len*2] = 0;
216 200 return (1);
217 201 }
218 202
219 203 static char hex[16] = {
220 204 '0', '1', '2', '3', '4', '5', '6', '7',
221 205 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
222 206 };
223 207
224 208 static char
225 209 hexval(c)
226 210 char c;
227 211 {
228 212 if (c >= '0' && c <= '9') {
229 213 return (c - '0');
230 214 } else if (c >= 'a' && c <= 'z') {
231 215 return (c - 'a' + 10);
232 216 } else if (c >= 'A' && c <= 'Z') {
233 217 return (c - 'A' + 10);
234 218 } else {
235 219 return (-1);
236 220 }
237 221 }
238 222
239 223 /*
240 224 * Generic key length/algorithm version of xencrypt().
241 225 *
242 226 * Encrypt a secret key given passwd.
243 227 * The secret key is passed in hex notation.
244 228 * Arg encrypted_secret will be set to point to the encrypted
245 229 * secret key (NUL term, hex notation).
246 230 *
247 231 * Its length must be a multiple of 16 hex digits (64 bits).
248 232 *
249 233 * For 192-0 (AUTH_DES), then encrypt using the same method as xencrypt().
250 234 *
251 235 * If arg do_chksum is TRUE, append the checksum before the encrypt.
252 236 * For 192-0, the checksum is done the same as in xencrypt(). For
253 237 * bigger keys, MD5 is used.
254 238 *
255 239 * Arg netname can be NULL for 192-0.
256 240 */
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
257 241 int
258 242 xencrypt_g(
259 243 char *secret, /* in */
260 244 keylen_t keylen, /* in */
261 245 algtype_t algtype, /* in */
262 246 const char *passwd, /* in */
263 247 const char netname[], /* in */
264 248 char **encrypted_secret, /* out */
265 249 bool_t do_chksum) /* in */
266 250 {
267 -/* EXPORT DELETE START */
268 251 des_block key;
269 252 char ivec[8];
270 253 char *binkeybuf;
271 254 int err;
272 255 const int classic_des = keylen == 192 && algtype == 0;
273 256 const int hexkeybytes = BITS2NIBBLES(keylen);
274 257 const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
275 258 const int binkeybytes = do_chksum ? keylen/8 + keychecksumsize/2 :
276 259 keylen/8;
277 260 const int bufsize = do_chksum ? hexkeybytes + keychecksumsize + 1 :
278 261 hexkeybytes + 1;
279 262 char *hexkeybuf;
280 263
281 264 if (!secret || !keylen || !passwd || !encrypted_secret)
282 265 return (0);
283 266
284 267 if ((hexkeybuf = malloc(bufsize)) == 0)
285 268 return (0);
286 269
287 270 (void) memcpy(hexkeybuf, secret, hexkeybytes);
288 271 if (do_chksum)
289 272 if (classic_des) {
290 273 (void) memcpy(hexkeybuf + hexkeybytes, secret,
291 274 keychecksumsize);
292 275 } else {
293 276 MD5_CTX md5_ctx;
294 277 char md5hexbuf[MD5HEXSIZE + 1] = {0};
295 278 uint8_t digest[MD5HEXSIZE/2];
296 279
297 280 MD5Init(&md5_ctx);
298 281 MD5Update(&md5_ctx, (unsigned char *)hexkeybuf,
299 282 hexkeybytes);
300 283 MD5Final(digest, &md5_ctx);
301 284
302 285 /* convert md5 binary digest to hex */
303 286 (void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
304 287
305 288 /* append the hex md5 string to the end of the key */
306 289 (void) memcpy(hexkeybuf + hexkeybytes,
307 290 (void *)md5hexbuf, MD5HEXSIZE);
308 291 }
309 292 hexkeybuf[bufsize - 1] = 0;
310 293
311 294 if (binkeybytes > MAX_KEY_CRYPT_LEN) {
312 295 free(hexkeybuf);
313 296 return (0);
314 297 }
315 298 if ((binkeybuf = malloc((unsigned)binkeybytes)) == 0) {
316 299 free(hexkeybuf);
317 300 return (0);
318 301 }
319 302
320 303 (void) hex2bin(binkeybytes, hexkeybuf, binkeybuf);
321 304 if (classic_des)
322 305 (void) passwd2des((char *)passwd, key.c);
323 306 else
324 307 if (netname)
325 308 (void) passwd2des_g(passwd, netname,
326 309 (int)strlen(netname), &key, FALSE);
327 310 else {
328 311 free(hexkeybuf);
329 312 return (0);
330 313 }
331 314
332 315 (void) memset(ivec, 0, 8);
333 316
334 317 err = cbc_crypt(key.c, binkeybuf, binkeybytes, DES_ENCRYPT | DES_HW,
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
335 318 ivec);
336 319 if (DES_FAILED(err)) {
337 320 free(hexkeybuf);
338 321 free(binkeybuf);
339 322 return (0);
340 323 }
341 324 (void) bin2hex(binkeybytes, (unsigned char *) binkeybuf, hexkeybuf);
342 325 free(binkeybuf);
343 326 *encrypted_secret = hexkeybuf;
344 327 return (1);
345 -#if 0
346 -/* EXPORT DELETE END */
347 - return (0);
348 -/* EXPORT DELETE START */
349 -#endif
350 -/* EXPORT DELETE END */
351 328 }
352 329
353 330 /*
354 331 * Generic key len and alg type for version of xdecrypt.
355 332 *
356 333 * Decrypt secret key using passwd. The decrypted secret key
357 334 * *overwrites* the supplied encrypted secret key.
358 335 * The secret key is passed and returned in hex notation.
359 336 * Once again, the length is a multiple of 16 hex digits.
360 337 *
361 338 * If 'do_chksum' is TRUE, the 'secret' buffer is assumed to contain
362 339 * a checksum calculated by a call to xencrypt_g().
363 340 *
364 341 * If keylen is 192 and algtype is 0, then decrypt the same way
365 342 * as xdecrypt().
366 343 *
367 344 * Arg netname can be NULL for 192-0.
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
368 345 */
369 346 int
370 347 xdecrypt_g(
371 348 char *secret, /* out */
372 349 int keylen, /* in */
373 350 int algtype, /* in */
374 351 const char *passwd, /* in */
375 352 const char netname[], /* in */
376 353 bool_t do_chksum) /* in */
377 354 {
378 -/* EXPORT DELETE START */
379 355 des_block key;
380 356 char ivec[8];
381 357 char *buf;
382 358 int err;
383 359 int len;
384 360 const int classic_des = keylen == 192 && algtype == 0;
385 361 const int hexkeybytes = BITS2NIBBLES(keylen);
386 362 const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
387 363
388 364 len = (int)strlen(secret) / 2;
389 365 if (len > MAX_KEY_CRYPT_LEN)
390 366 return (0);
391 367 if ((buf = malloc((unsigned)len)) == 0)
392 368 return (0);
393 369
394 370 (void) hex2bin(len, secret, buf);
395 371 if (classic_des)
396 372 (void) passwd2des((char *)passwd, key.c);
397 373 else
398 374 if (netname)
399 375 (void) passwd2des_g(passwd, netname,
400 376 (int)strlen(netname), &key, FALSE);
401 377 else {
402 378 free(buf);
403 379 return (0);
404 380 }
405 381 (void) memset(ivec, 0, 8);
406 382
407 383 err = cbc_crypt(key.c, buf, len, DES_DECRYPT | DES_HW, ivec);
408 384 if (DES_FAILED(err)) {
409 385 free(buf);
410 386 return (0);
411 387 }
412 388 (void) bin2hex(len, (unsigned char *) buf, secret);
413 389 free(buf);
414 390
415 391 if (do_chksum)
416 392 if (classic_des) {
417 393 if (memcmp(secret, &(secret[hexkeybytes]),
418 394 keychecksumsize) != 0) {
419 395 secret[0] = 0;
420 396 return (0);
421 397 }
422 398 } else {
423 399 MD5_CTX md5_ctx;
424 400 char md5hexbuf[MD5HEXSIZE + 1] = {0};
425 401 uint8_t digest[MD5HEXSIZE/2];
426 402
427 403 MD5Init(&md5_ctx);
428 404 MD5Update(&md5_ctx, (unsigned char *)secret,
429 405 hexkeybytes);
430 406 MD5Final(digest, &md5_ctx);
431 407
432 408 /* convert md5 binary digest to hex */
433 409 (void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
434 410
435 411 /* does the digest match the appended one? */
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
436 412 if (memcmp(&(secret[hexkeybytes]),
437 413 md5hexbuf, MD5HEXSIZE) != 0) {
438 414 secret[0] = 0;
439 415 return (0);
440 416 }
441 417 }
442 418
443 419 secret[hexkeybytes] = '\0';
444 420
445 421 return (1);
446 -#if 0
447 -/* EXPORT DELETE END */
448 - return (0);
449 -/* EXPORT DELETE START */
450 -#endif
451 -/* EXPORT DELETE END */
452 422 }
453 423
454 424
455 425 /*
456 426 * Modified version of passwd2des(). passwd2des_g() uses the Kerberos
457 427 * RFC 1510 algorithm to generate a DES key from a user password
458 428 * and mix-in string. The mix-in is expected to be the netname.
459 429 * This function to be used only for extended Diffie-Hellman keys.
460 430 *
461 431 * If altarg is TRUE, reverse the concat of passwd and mix-in.
462 432 */
463 433 int
464 434 passwd2des_g(
465 435 const char *pw,
466 436 const char *mixin,
467 437 int len,
468 438 des_block *key, /* out */
469 439 bool_t altalg)
470 440 {
471 441
472 442 int i, j, incr = 1;
473 443 des_block ivec, tkey;
474 444 char *text;
475 445 int plen, tlen;
476 446
477 447 (void) memset(tkey.c, 0, 8);
478 448 (void) memset(ivec.c, 0, 8);
479 449
480 450
481 451 /*
482 452 * Concatentate the password and the mix-in string, fan-fold and XOR them
483 453 * to the required eight byte initial DES key. Since passwords can be
484 454 * expected to use mostly seven bit ASCII, left shift the password one
485 455 * bit in order to preserve as much key space as possible.
486 456 */
487 457
488 458 #define KEYLEN sizeof (tkey.c)
489 459 plen = strlen(pw);
490 460 tlen = ((plen + len + (KEYLEN-1))/KEYLEN)*KEYLEN;
491 461 if ((text = malloc(tlen)) == NULL) {
492 462 return (0);
493 463 }
494 464
495 465 (void) memset(text, 0, tlen);
496 466
497 467 if (!altalg) {
498 468
499 469 /*
500 470 * Concatenate the password and the mix-in string, fan-fold and XOR them
501 471 * to the required eight byte initial DES key. Since passwords can be
502 472 * expected to use mostly seven bit ASCII, left shift the password one
503 473 * bit in order to preserve as much key space as possible.
504 474 */
505 475 (void) memcpy(text, pw, plen);
506 476 (void) memcpy(&text[plen], mixin, len);
507 477
508 478 for (i = 0, j = 0; pw[j]; j++) {
509 479 tkey.c[i] ^= pw[j] << 1;
510 480 i += incr;
511 481 if (i == 8) {
512 482 i = 7;
513 483 incr = -incr;
514 484 } else if (i == -1) {
515 485 i = 0;
516 486 incr = -incr;
517 487 }
518 488 }
519 489
520 490 for (j = 0; j < len; j++) {
521 491 tkey.c[i] ^= mixin[j];
522 492 i += incr;
523 493 if (i == 8) {
524 494 i = 7;
525 495 incr = -incr;
526 496 } else if (i == -1) {
527 497 i = 0;
528 498 incr = -incr;
529 499 }
530 500 }
531 501 } else { /* use alternative algorithm */
532 502 (void) memcpy(text, mixin, len);
533 503 (void) memcpy(&text[len], pw, plen);
534 504
535 505 for (i = 0, j = 0; j < len; j++) {
536 506 tkey.c[i] ^= mixin[j];
537 507 i += incr;
538 508 if (i == 8) {
539 509 i = 7;
540 510 incr = -incr;
541 511 } else if (i == -1) {
542 512 i = 0;
543 513 incr = -incr;
544 514 }
545 515 }
546 516
547 517 for (j = 0; pw[j]; j++) {
548 518 tkey.c[i] ^= pw[j] << 1;
549 519 i += incr;
550 520 if (i == 8) {
551 521 i = 7;
552 522 incr = -incr;
553 523 } else if (i == -1) {
554 524 i = 0;
555 525 incr = -incr;
556 526 }
557 527 }
558 528 }
559 529 des_setparity_g(&tkey);
560 530
561 531 /*
562 532 * Use the temporary key to produce a DES CBC checksum for the text
563 533 * string; cbc_crypt returns the checksum in the ivec.
564 534 */
565 535 (void) cbc_crypt(tkey.c, text, tlen, DES_ENCRYPT|DES_HW, ivec.c);
566 536 des_setparity_g(&ivec);
567 537 free(text);
568 538
569 539 if (weak_DES_key(ivec)) {
570 540 ivec.c[7] ^= 0xf0;
571 541 /*
572 542 * XORing with 0xf0 preserves parity, so no need to check
573 543 * that again.
574 544 */
575 545 }
576 546
577 547 (void) memcpy((*key).c, ivec.c, sizeof (ivec.c));
578 548
579 549 return (1);
580 550
581 551 }
582 552
583 553 struct DESkey {
584 554 uint32_t h1;
585 555 uint32_t h2;
586 556 };
587 557
588 558 /*
589 559 * Weak and semiweak keys from "Applied Cryptography", second edition,
590 560 * by Bruce Schneier, Wiley 1996.
591 561 */
592 562 static struct DESkey weakDESkeys[] = {
593 563 /* Weak keys */
594 564 {0x01010101, 0x01010101},
595 565 {0x1f1f1f1f, 0x1f1f1f1f},
596 566 {0xe0e0e0e0, 0xe0e0e0e0},
597 567 {0xfefefefe, 0xfefefefe},
598 568 /* Semiweak keys */
599 569 {0x01fe01fe, 0x01fe01fe},
600 570 {0x1fe01fe0, 0x0ef10ef1},
601 571 {0x01e001e0, 0x01f101f1},
602 572 {0x1ffe1ffe, 0x0efe0efe},
603 573 {0x011f011f, 0x010e010e},
604 574 {0xe0fee0fe, 0xf1fef1fe},
605 575 {0xfe01fe01, 0xfe01fe01},
606 576 {0xe01fe01f, 0xf10ef10e},
607 577 {0xe001e001, 0xf101f101},
608 578 {0xfe1ffe1f, 0xfe0efe0e},
609 579 {0x1f011f01, 0x0e010e01},
610 580 {0xfee0fee0, 0xfef1fef1}
611 581 };
612 582
613 583 static int
614 584 weak_DES_key(des_block db)
615 585 {
616 586 int i;
617 587
618 588 for (i = 0; i < sizeof (weakDESkeys)/sizeof (struct DESkey); i++) {
619 589 if (weakDESkeys[i].h1 == db.key.high &&
620 590 weakDESkeys[i].h2 == db.key.low)
621 591 return (1);
622 592 }
623 593
624 594 return (0);
625 595 }
↓ open down ↓ |
164 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX