4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 * Portions of this source code were derived from Berkeley 4.3 BSD
33 * under license from the Regents of the University of California.
37 * Hex encryption/decryption and utility routines
42 #include <sys/types.h>
44 #include <rpc/key_prot.h> /* for KEYCHECKSUMSIZE */
45 #include <rpc/des_crypt.h>
47 #include <rpcsvc/nis_dhext.h>
52 static int bin2hex(int len
, unsigned char *binnum
, char *hexnum
);
53 static int hex2bin(int len
, char *hexnum
, char *binnum
);
54 static char hex
[]; /* forward */
57 int passwd2des(char *, char *);
58 static int weak_DES_key(des_block
);
61 * For export control reasons, we want to limit the maximum size of
62 * data that can be encrypted or decrypted. We limit this to 1024
63 * bits of key data, which amounts to 128 bytes.
65 * For the extended DH project, we have increased it to
66 * 144 bytes (128key + 16checksum) to accomadate all the 128 bytes
67 * being used by the new 1024bit keys plus 16 bytes MD5 checksum.
68 * We discussed this with Sun's export control office and lawyers
69 * and we have reason to believe this is ok for export.
71 #define MAX_KEY_CRYPT_LEN 144
74 * Encrypt a secret key given passwd
75 * The secret key is passed and returned in hex notation.
76 * Its length must be a multiple of 16 hex digits (64 bits).
79 xencrypt(secret
, passwd
)
89 len
= (int)strlen(secret
) / 2;
90 if (len
> MAX_KEY_CRYPT_LEN
)
92 buf
= malloc((unsigned)len
);
93 (void) hex2bin(len
, secret
, buf
);
94 (void) passwd2des(passwd
, key
);
95 (void) memset(ivec
, 0, 8);
97 err
= cbc_crypt(key
, buf
, len
, DES_ENCRYPT
| DES_HW
, ivec
);
98 if (DES_FAILED(err
)) {
102 (void) bin2hex(len
, (unsigned char *) buf
, secret
);
108 * Decrypt secret key using passwd
109 * The secret key is passed and returned in hex notation.
110 * Once again, the length is a multiple of 16 hex digits
113 xdecrypt(secret
, passwd
)
123 len
= (int)strlen(secret
) / 2;
124 if (len
> MAX_KEY_CRYPT_LEN
)
126 buf
= malloc((unsigned)len
);
128 (void) hex2bin(len
, secret
, buf
);
129 (void) passwd2des(passwd
, key
);
130 (void) memset(ivec
, 0, 8);
132 err
= cbc_crypt(key
, buf
, len
, DES_DECRYPT
| DES_HW
, ivec
);
133 if (DES_FAILED(err
)) {
137 (void) bin2hex(len
, (unsigned char *) buf
, secret
);
143 * Turn password into DES key
152 (void) memset(key
, 0, 8);
153 for (i
= 0; *pw
; i
= (i
+1) % 8) {
154 key
[i
] ^= *pw
++ << 1;
162 * Hex to binary conversion
165 hex2bin(len
, hexnum
, binnum
)
172 for (i
= 0; i
< len
; i
++) {
173 *binnum
++ = 16 * hexval(hexnum
[2 * i
]) +
174 hexval(hexnum
[2 * i
+ 1]);
180 * Binary to hex conversion
183 bin2hex(len
, binnum
, hexnum
)
185 unsigned char *binnum
;
191 for (i
= 0; i
< len
; i
++) {
193 hexnum
[i
*2] = hex
[val
>> 4];
194 hexnum
[i
*2+1] = hex
[val
& 0xf];
200 static char hex
[16] = {
201 '0', '1', '2', '3', '4', '5', '6', '7',
202 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
209 if (c
>= '0' && c
<= '9') {
211 } else if (c
>= 'a' && c
<= 'z') {
212 return (c
- 'a' + 10);
213 } else if (c
>= 'A' && c
<= 'Z') {
214 return (c
- 'A' + 10);
221 * Generic key length/algorithm version of xencrypt().
223 * Encrypt a secret key given passwd.
224 * The secret key is passed in hex notation.
225 * Arg encrypted_secret will be set to point to the encrypted
226 * secret key (NUL term, hex notation).
228 * Its length must be a multiple of 16 hex digits (64 bits).
230 * For 192-0 (AUTH_DES), then encrypt using the same method as xencrypt().
232 * If arg do_chksum is TRUE, append the checksum before the encrypt.
233 * For 192-0, the checksum is done the same as in xencrypt(). For
234 * bigger keys, MD5 is used.
236 * Arg netname can be NULL for 192-0.
240 char *secret
, /* in */
241 keylen_t keylen
, /* in */
242 algtype_t algtype
, /* in */
243 const char *passwd
, /* in */
244 const char netname
[], /* in */
245 char **encrypted_secret
, /* out */
246 bool_t do_chksum
) /* in */
252 const int classic_des
= keylen
== 192 && algtype
== 0;
253 const int hexkeybytes
= BITS2NIBBLES(keylen
);
254 const int keychecksumsize
= classic_des
? KEYCHECKSUMSIZE
: MD5HEXSIZE
;
255 const int binkeybytes
= do_chksum
? keylen
/8 + keychecksumsize
/2 :
257 const int bufsize
= do_chksum
? hexkeybytes
+ keychecksumsize
+ 1 :
261 if (!secret
|| !keylen
|| !passwd
|| !encrypted_secret
)
264 if ((hexkeybuf
= malloc(bufsize
)) == 0)
267 (void) memcpy(hexkeybuf
, secret
, hexkeybytes
);
270 (void) memcpy(hexkeybuf
+ hexkeybytes
, secret
,
274 char md5hexbuf
[MD5HEXSIZE
+ 1] = {0};
275 uint8_t digest
[MD5HEXSIZE
/2];
278 MD5Update(&md5_ctx
, (unsigned char *)hexkeybuf
,
280 MD5Final(digest
, &md5_ctx
);
282 /* convert md5 binary digest to hex */
283 (void) bin2hex(MD5HEXSIZE
/2, digest
, md5hexbuf
);
285 /* append the hex md5 string to the end of the key */
286 (void) memcpy(hexkeybuf
+ hexkeybytes
,
287 (void *)md5hexbuf
, MD5HEXSIZE
);
289 hexkeybuf
[bufsize
- 1] = 0;
291 if (binkeybytes
> MAX_KEY_CRYPT_LEN
) {
295 if ((binkeybuf
= malloc((unsigned)binkeybytes
)) == 0) {
300 (void) hex2bin(binkeybytes
, hexkeybuf
, binkeybuf
);
302 (void) passwd2des((char *)passwd
, key
.c
);
305 (void) passwd2des_g(passwd
, netname
,
306 (int)strlen(netname
), &key
, FALSE
);
312 (void) memset(ivec
, 0, 8);
314 err
= cbc_crypt(key
.c
, binkeybuf
, binkeybytes
, DES_ENCRYPT
| DES_HW
,
316 if (DES_FAILED(err
)) {
321 (void) bin2hex(binkeybytes
, (unsigned char *) binkeybuf
, hexkeybuf
);
323 *encrypted_secret
= hexkeybuf
;
328 * Generic key len and alg type for version of xdecrypt.
330 * Decrypt secret key using passwd. The decrypted secret key
331 * *overwrites* the supplied encrypted secret key.
332 * The secret key is passed and returned in hex notation.
333 * Once again, the length is a multiple of 16 hex digits.
335 * If 'do_chksum' is TRUE, the 'secret' buffer is assumed to contain
336 * a checksum calculated by a call to xencrypt_g().
338 * If keylen is 192 and algtype is 0, then decrypt the same way
341 * Arg netname can be NULL for 192-0.
345 char *secret
, /* out */
347 int algtype
, /* in */
348 const char *passwd
, /* in */
349 const char netname
[], /* in */
350 bool_t do_chksum
) /* in */
357 const int classic_des
= keylen
== 192 && algtype
== 0;
358 const int hexkeybytes
= BITS2NIBBLES(keylen
);
359 const int keychecksumsize
= classic_des
? KEYCHECKSUMSIZE
: MD5HEXSIZE
;
361 len
= (int)strlen(secret
) / 2;
362 if (len
> MAX_KEY_CRYPT_LEN
)
364 if ((buf
= malloc((unsigned)len
)) == 0)
367 (void) hex2bin(len
, secret
, buf
);
369 (void) passwd2des((char *)passwd
, key
.c
);
372 (void) passwd2des_g(passwd
, netname
,
373 (int)strlen(netname
), &key
, FALSE
);
378 (void) memset(ivec
, 0, 8);
380 err
= cbc_crypt(key
.c
, buf
, len
, DES_DECRYPT
| DES_HW
, ivec
);
381 if (DES_FAILED(err
)) {
385 (void) bin2hex(len
, (unsigned char *) buf
, secret
);
390 if (memcmp(secret
, &(secret
[hexkeybytes
]),
391 keychecksumsize
) != 0) {
397 char md5hexbuf
[MD5HEXSIZE
+ 1] = {0};
398 uint8_t digest
[MD5HEXSIZE
/2];
401 MD5Update(&md5_ctx
, (unsigned char *)secret
,
403 MD5Final(digest
, &md5_ctx
);
405 /* convert md5 binary digest to hex */
406 (void) bin2hex(MD5HEXSIZE
/2, digest
, md5hexbuf
);
408 /* does the digest match the appended one? */
409 if (memcmp(&(secret
[hexkeybytes
]),
410 md5hexbuf
, MD5HEXSIZE
) != 0) {
416 secret
[hexkeybytes
] = '\0';
423 * Modified version of passwd2des(). passwd2des_g() uses the Kerberos
424 * RFC 1510 algorithm to generate a DES key from a user password
425 * and mix-in string. The mix-in is expected to be the netname.
426 * This function to be used only for extended Diffie-Hellman keys.
428 * If altarg is TRUE, reverse the concat of passwd and mix-in.
435 des_block
*key
, /* out */
440 des_block ivec
, tkey
;
444 (void) memset(tkey
.c
, 0, 8);
445 (void) memset(ivec
.c
, 0, 8);
449 * Concatentate the password and the mix-in string, fan-fold and XOR them
450 * to the required eight byte initial DES key. Since passwords can be
451 * expected to use mostly seven bit ASCII, left shift the password one
452 * bit in order to preserve as much key space as possible.
455 #define KEYLEN sizeof (tkey.c)
457 tlen
= ((plen
+ len
+ (KEYLEN
-1))/KEYLEN
)*KEYLEN
;
458 if ((text
= malloc(tlen
)) == NULL
) {
462 (void) memset(text
, 0, tlen
);
467 * Concatenate the password and the mix-in string, fan-fold and XOR them
468 * to the required eight byte initial DES key. Since passwords can be
469 * expected to use mostly seven bit ASCII, left shift the password one
470 * bit in order to preserve as much key space as possible.
472 (void) memcpy(text
, pw
, plen
);
473 (void) memcpy(&text
[plen
], mixin
, len
);
475 for (i
= 0, j
= 0; pw
[j
]; j
++) {
476 tkey
.c
[i
] ^= pw
[j
] << 1;
481 } else if (i
== -1) {
487 for (j
= 0; j
< len
; j
++) {
488 tkey
.c
[i
] ^= mixin
[j
];
493 } else if (i
== -1) {
498 } else { /* use alternative algorithm */
499 (void) memcpy(text
, mixin
, len
);
500 (void) memcpy(&text
[len
], pw
, plen
);
502 for (i
= 0, j
= 0; j
< len
; j
++) {
503 tkey
.c
[i
] ^= mixin
[j
];
508 } else if (i
== -1) {
514 for (j
= 0; pw
[j
]; j
++) {
515 tkey
.c
[i
] ^= pw
[j
] << 1;
520 } else if (i
== -1) {
526 des_setparity_g(&tkey
);
529 * Use the temporary key to produce a DES CBC checksum for the text
530 * string; cbc_crypt returns the checksum in the ivec.
532 (void) cbc_crypt(tkey
.c
, text
, tlen
, DES_ENCRYPT
|DES_HW
, ivec
.c
);
533 des_setparity_g(&ivec
);
536 if (weak_DES_key(ivec
)) {
539 * XORing with 0xf0 preserves parity, so no need to check
544 (void) memcpy((*key
).c
, ivec
.c
, sizeof (ivec
.c
));
556 * Weak and semiweak keys from "Applied Cryptography", second edition,
557 * by Bruce Schneier, Wiley 1996.
559 static struct DESkey weakDESkeys
[] = {
561 {0x01010101, 0x01010101},
562 {0x1f1f1f1f, 0x1f1f1f1f},
563 {0xe0e0e0e0, 0xe0e0e0e0},
564 {0xfefefefe, 0xfefefefe},
566 {0x01fe01fe, 0x01fe01fe},
567 {0x1fe01fe0, 0x0ef10ef1},
568 {0x01e001e0, 0x01f101f1},
569 {0x1ffe1ffe, 0x0efe0efe},
570 {0x011f011f, 0x010e010e},
571 {0xe0fee0fe, 0xf1fef1fe},
572 {0xfe01fe01, 0xfe01fe01},
573 {0xe01fe01f, 0xf10ef10e},
574 {0xe001e001, 0xf101f101},
575 {0xfe1ffe1f, 0xfe0efe0e},
576 {0x1f011f01, 0x0e010e01},
577 {0xfee0fee0, 0xfef1fef1}
581 weak_DES_key(des_block db
)
585 for (i
= 0; i
< sizeof (weakDESkeys
)/sizeof (struct DESkey
); i
++) {
586 if (weakDESkeys
[i
].h1
== db
.key
.high
&&
587 weakDESkeys
[i
].h2
== db
.key
.low
)