Print this page
first pass


  43 #include <stdio.h>
  44 #include <stdlib.h>
  45 #include <sys/types.h>
  46 #include <rpc/rpc.h>
  47 #include <rpc/key_prot.h>   /* for KEYCHECKSUMSIZE */
  48 #include <rpc/des_crypt.h>
  49 #include <string.h>
  50 #include <rpcsvc/nis_dhext.h>
  51 #include <md5.h>
  52 
  53 #define MD5HEXSIZE      32
  54 
  55 extern int bin2hex(int len, unsigned char *binnum, char *hexnum);
  56 extern int hex2bin(int len, char *hexnum, char *binnum);
  57 static char hex[];      /* forward */
  58 static char hexval();
  59 
  60 int passwd2des(char *, char *);
  61 static int weak_DES_key(des_block);
  62 
  63 /* EXPORT DELETE START */
  64 /*
  65  * For export control reasons, we want to limit the maximum size of
  66  * data that can be encrypted or decrypted.  We limit this to 1024
  67  * bits of key data, which amounts to 128 bytes.
  68  *
  69  * For the extended DH project, we have increased it to
  70  * 144 bytes (128key + 16checksum) to accomadate all the 128 bytes
  71  * being used by the new 1024bit keys plus 16 bytes MD5 checksum.
  72  * We discussed this with Sun's export control office and lawyers
  73  * and we have reason to believe this is ok for export.
  74  */
  75 #define MAX_KEY_CRYPT_LEN       144
  76 /* EXPORT DELETE END */
  77 
  78 /*
  79  * Encrypt a secret key given passwd
  80  * The secret key is passed and returned in hex notation.
  81  * Its length must be a multiple of 16 hex digits (64 bits).
  82  */
  83 int
  84 xencrypt(secret, passwd)
  85         char *secret;
  86         char *passwd;
  87 {
  88 /* EXPORT DELETE START */
  89         char key[8];
  90         char ivec[8];
  91         char *buf;
  92         int err;
  93         int len;
  94 
  95         len = (int)strlen(secret) / 2;
  96         if (len > MAX_KEY_CRYPT_LEN)
  97                 return (0);
  98         buf = malloc((unsigned)len);
  99         (void) hex2bin(len, secret, buf);
 100         (void) passwd2des(passwd, key);
 101         (void) memset(ivec, 0, 8);
 102 
 103         err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
 104         if (DES_FAILED(err)) {
 105                 free(buf);
 106                 return (0);
 107         }
 108         (void) bin2hex(len, (unsigned char *) buf, secret);
 109         free(buf);
 110         return (1);
 111 #if 0
 112 /* EXPORT DELETE END */
 113         return (0);
 114 /* EXPORT DELETE START */
 115 #endif
 116 /* EXPORT DELETE END */
 117 }
 118 
 119 /*
 120  * Decrypt secret key using passwd
 121  * The secret key is passed and returned in hex notation.
 122  * Once again, the length is a multiple of 16 hex digits
 123  */
 124 int
 125 xdecrypt(secret, passwd)
 126         char *secret;
 127         char *passwd;
 128 {
 129 /* EXPORT DELETE START */
 130         char key[8];
 131         char ivec[8];
 132         char *buf;
 133         int err;
 134         int len;
 135 
 136         len = (int)strlen(secret) / 2;
 137         if (len > MAX_KEY_CRYPT_LEN)
 138                 return (0);
 139         buf = malloc((unsigned)len);
 140 
 141         (void) hex2bin(len, secret, buf);
 142         (void) passwd2des(passwd, key);
 143         (void) memset(ivec, 0, 8);
 144 
 145         err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
 146         if (DES_FAILED(err)) {
 147                 free(buf);
 148                 return (0);
 149         }
 150         (void) bin2hex(len, (unsigned char *) buf, secret);
 151         free(buf);
 152         return (1);
 153 #if 0
 154 /* EXPORT DELETE END */
 155         return (0);
 156 /* EXPORT DELETE START */
 157 #endif
 158 /* EXPORT DELETE END */
 159 }
 160 
 161 /*
 162  * Turn password into DES key
 163  */
 164 int
 165 passwd2des(pw, key)
 166         char *pw;
 167         char *key;
 168 {
 169         int i;
 170 
 171         (void) memset(key, 0, 8);
 172         for (i = 0; *pw; i = (i+1) % 8) {
 173                 key[i] ^= *pw++ << 1;
 174         }
 175         des_setparity(key);
 176         return (1);
 177 }
 178 


 247  * Its length must be a multiple of 16 hex digits (64 bits).
 248  *
 249  * For 192-0 (AUTH_DES), then encrypt using the same method as xencrypt().
 250  *
 251  * If arg do_chksum is TRUE, append the checksum before the encrypt.
 252  * For 192-0, the checksum is done the same as in xencrypt().  For
 253  * bigger keys, MD5 is used.
 254  *
 255  * Arg netname can be NULL for 192-0.
 256  */
 257 int
 258 xencrypt_g(
 259         char *secret,                   /* in  */
 260         keylen_t keylen,                /* in  */
 261         algtype_t algtype,              /* in  */
 262         const char *passwd,             /* in  */
 263         const char netname[],           /* in  */
 264         char **encrypted_secret,        /* out */
 265         bool_t do_chksum)               /* in  */
 266 {
 267 /* EXPORT DELETE START */
 268         des_block key;
 269         char ivec[8];
 270         char *binkeybuf;
 271         int err;
 272         const int classic_des = keylen == 192 && algtype == 0;
 273         const int hexkeybytes = BITS2NIBBLES(keylen);
 274         const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
 275         const int binkeybytes = do_chksum ? keylen/8 + keychecksumsize/2 :
 276                 keylen/8;
 277         const int bufsize = do_chksum ? hexkeybytes + keychecksumsize + 1 :
 278                 hexkeybytes + 1;
 279         char *hexkeybuf;
 280 
 281         if (!secret || !keylen || !passwd || !encrypted_secret)
 282                 return (0);
 283 
 284         if ((hexkeybuf = malloc(bufsize)) == 0)
 285                 return (0);
 286 
 287         (void) memcpy(hexkeybuf, secret, hexkeybytes);


 325                         (void) passwd2des_g(passwd, netname,
 326                                         (int)strlen(netname), &key, FALSE);
 327                 else {
 328                         free(hexkeybuf);
 329                         return (0);
 330                 }
 331 
 332         (void) memset(ivec, 0, 8);
 333 
 334         err = cbc_crypt(key.c, binkeybuf, binkeybytes, DES_ENCRYPT | DES_HW,
 335                         ivec);
 336         if (DES_FAILED(err)) {
 337                 free(hexkeybuf);
 338                 free(binkeybuf);
 339                 return (0);
 340         }
 341         (void) bin2hex(binkeybytes, (unsigned char *) binkeybuf, hexkeybuf);
 342         free(binkeybuf);
 343         *encrypted_secret = hexkeybuf;
 344         return (1);
 345 #if 0
 346 /* EXPORT DELETE END */
 347         return (0);
 348 /* EXPORT DELETE START */
 349 #endif
 350 /* EXPORT DELETE END */
 351 }
 352 
 353 /*
 354  * Generic key len and alg type for version of xdecrypt.
 355  *
 356  * Decrypt secret key using passwd.  The decrypted secret key
 357  * *overwrites* the supplied encrypted secret key.
 358  * The secret key is passed and returned in hex notation.
 359  * Once again, the length is a multiple of 16 hex digits.
 360  *
 361  * If 'do_chksum' is TRUE, the 'secret' buffer is assumed to contain
 362  * a checksum calculated by a call to xencrypt_g().
 363  *
 364  * If keylen is 192 and algtype is 0, then decrypt the same way
 365  * as xdecrypt().
 366  *
 367  * Arg netname can be NULL for 192-0.
 368  */
 369 int
 370 xdecrypt_g(
 371         char *secret,           /* out  */
 372         int keylen,             /* in  */
 373         int algtype,            /* in  */
 374         const char *passwd,     /* in  */
 375         const char netname[],   /* in  */
 376         bool_t do_chksum)       /* in  */
 377 {
 378 /* EXPORT DELETE START */
 379         des_block key;
 380         char ivec[8];
 381         char *buf;
 382         int err;
 383         int len;
 384         const int classic_des = keylen == 192 && algtype == 0;
 385         const int hexkeybytes = BITS2NIBBLES(keylen);
 386         const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
 387 
 388         len = (int)strlen(secret) / 2;
 389         if (len > MAX_KEY_CRYPT_LEN)
 390                 return (0);
 391         if ((buf = malloc((unsigned)len)) == 0)
 392                 return (0);
 393 
 394         (void) hex2bin(len, secret, buf);
 395         if (classic_des)
 396                 (void) passwd2des((char *)passwd, key.c);
 397         else
 398                 if (netname)


 426 
 427                         MD5Init(&md5_ctx);
 428                         MD5Update(&md5_ctx, (unsigned char *)secret,
 429                                         hexkeybytes);
 430                         MD5Final(digest, &md5_ctx);
 431 
 432                         /* convert md5 binary digest to hex */
 433                         (void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
 434 
 435                         /* does the digest match the appended one? */
 436                         if (memcmp(&(secret[hexkeybytes]),
 437                                         md5hexbuf, MD5HEXSIZE) != 0) {
 438                                 secret[0] = 0;
 439                                 return (0);
 440                         }
 441                 }
 442 
 443         secret[hexkeybytes] = '\0';
 444 
 445         return (1);
 446 #if 0
 447 /* EXPORT DELETE END */
 448         return (0);
 449 /* EXPORT DELETE START */
 450 #endif
 451 /* EXPORT DELETE END */
 452 }
 453 
 454 
 455 /*
 456  * Modified version of passwd2des(). passwd2des_g() uses the Kerberos
 457  * RFC 1510 algorithm to generate a DES key from a user password
 458  * and mix-in string. The mix-in is expected to be the netname.
 459  * This function to be used only for extended Diffie-Hellman keys.
 460  *
 461  * If altarg is TRUE, reverse the concat of passwd and mix-in.
 462  */
 463 int
 464 passwd2des_g(
 465         const char *pw,
 466         const char *mixin,
 467         int len,
 468         des_block *key, /* out */
 469         bool_t altalg)
 470 {
 471 




  43 #include <stdio.h>
  44 #include <stdlib.h>
  45 #include <sys/types.h>
  46 #include <rpc/rpc.h>
  47 #include <rpc/key_prot.h>   /* for KEYCHECKSUMSIZE */
  48 #include <rpc/des_crypt.h>
  49 #include <string.h>
  50 #include <rpcsvc/nis_dhext.h>
  51 #include <md5.h>
  52 
  53 #define MD5HEXSIZE      32
  54 
  55 extern int bin2hex(int len, unsigned char *binnum, char *hexnum);
  56 extern int hex2bin(int len, char *hexnum, char *binnum);
  57 static char hex[];      /* forward */
  58 static char hexval();
  59 
  60 int passwd2des(char *, char *);
  61 static int weak_DES_key(des_block);
  62 

  63 /*
  64  * For export control reasons, we want to limit the maximum size of
  65  * data that can be encrypted or decrypted.  We limit this to 1024
  66  * bits of key data, which amounts to 128 bytes.
  67  *
  68  * For the extended DH project, we have increased it to
  69  * 144 bytes (128key + 16checksum) to accomadate all the 128 bytes
  70  * being used by the new 1024bit keys plus 16 bytes MD5 checksum.
  71  * We discussed this with Sun's export control office and lawyers
  72  * and we have reason to believe this is ok for export.
  73  */
  74 #define MAX_KEY_CRYPT_LEN       144

  75 
  76 /*
  77  * Encrypt a secret key given passwd
  78  * The secret key is passed and returned in hex notation.
  79  * Its length must be a multiple of 16 hex digits (64 bits).
  80  */
  81 int
  82 xencrypt(secret, passwd)
  83         char *secret;
  84         char *passwd;
  85 {

  86         char key[8];
  87         char ivec[8];
  88         char *buf;
  89         int err;
  90         int len;
  91 
  92         len = (int)strlen(secret) / 2;
  93         if (len > MAX_KEY_CRYPT_LEN)
  94                 return (0);
  95         buf = malloc((unsigned)len);
  96         (void) hex2bin(len, secret, buf);
  97         (void) passwd2des(passwd, key);
  98         (void) memset(ivec, 0, 8);
  99 
 100         err = cbc_crypt(key, buf, len, DES_ENCRYPT | DES_HW, ivec);
 101         if (DES_FAILED(err)) {
 102                 free(buf);
 103                 return (0);
 104         }
 105         (void) bin2hex(len, (unsigned char *) buf, secret);
 106         free(buf);
 107         return (1);






 108 }
 109 
 110 /*
 111  * Decrypt secret key using passwd
 112  * The secret key is passed and returned in hex notation.
 113  * Once again, the length is a multiple of 16 hex digits
 114  */
 115 int
 116 xdecrypt(secret, passwd)
 117         char *secret;
 118         char *passwd;
 119 {

 120         char key[8];
 121         char ivec[8];
 122         char *buf;
 123         int err;
 124         int len;
 125 
 126         len = (int)strlen(secret) / 2;
 127         if (len > MAX_KEY_CRYPT_LEN)
 128                 return (0);
 129         buf = malloc((unsigned)len);
 130 
 131         (void) hex2bin(len, secret, buf);
 132         (void) passwd2des(passwd, key);
 133         (void) memset(ivec, 0, 8);
 134 
 135         err = cbc_crypt(key, buf, len, DES_DECRYPT | DES_HW, ivec);
 136         if (DES_FAILED(err)) {
 137                 free(buf);
 138                 return (0);
 139         }
 140         (void) bin2hex(len, (unsigned char *) buf, secret);
 141         free(buf);
 142         return (1);






 143 }
 144 
 145 /*
 146  * Turn password into DES key
 147  */
 148 int
 149 passwd2des(pw, key)
 150         char *pw;
 151         char *key;
 152 {
 153         int i;
 154 
 155         (void) memset(key, 0, 8);
 156         for (i = 0; *pw; i = (i+1) % 8) {
 157                 key[i] ^= *pw++ << 1;
 158         }
 159         des_setparity(key);
 160         return (1);
 161 }
 162 


 231  * Its length must be a multiple of 16 hex digits (64 bits).
 232  *
 233  * For 192-0 (AUTH_DES), then encrypt using the same method as xencrypt().
 234  *
 235  * If arg do_chksum is TRUE, append the checksum before the encrypt.
 236  * For 192-0, the checksum is done the same as in xencrypt().  For
 237  * bigger keys, MD5 is used.
 238  *
 239  * Arg netname can be NULL for 192-0.
 240  */
 241 int
 242 xencrypt_g(
 243         char *secret,                   /* in  */
 244         keylen_t keylen,                /* in  */
 245         algtype_t algtype,              /* in  */
 246         const char *passwd,             /* in  */
 247         const char netname[],           /* in  */
 248         char **encrypted_secret,        /* out */
 249         bool_t do_chksum)               /* in  */
 250 {

 251         des_block key;
 252         char ivec[8];
 253         char *binkeybuf;
 254         int err;
 255         const int classic_des = keylen == 192 && algtype == 0;
 256         const int hexkeybytes = BITS2NIBBLES(keylen);
 257         const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
 258         const int binkeybytes = do_chksum ? keylen/8 + keychecksumsize/2 :
 259                 keylen/8;
 260         const int bufsize = do_chksum ? hexkeybytes + keychecksumsize + 1 :
 261                 hexkeybytes + 1;
 262         char *hexkeybuf;
 263 
 264         if (!secret || !keylen || !passwd || !encrypted_secret)
 265                 return (0);
 266 
 267         if ((hexkeybuf = malloc(bufsize)) == 0)
 268                 return (0);
 269 
 270         (void) memcpy(hexkeybuf, secret, hexkeybytes);


 308                         (void) passwd2des_g(passwd, netname,
 309                                         (int)strlen(netname), &key, FALSE);
 310                 else {
 311                         free(hexkeybuf);
 312                         return (0);
 313                 }
 314 
 315         (void) memset(ivec, 0, 8);
 316 
 317         err = cbc_crypt(key.c, binkeybuf, binkeybytes, DES_ENCRYPT | DES_HW,
 318                         ivec);
 319         if (DES_FAILED(err)) {
 320                 free(hexkeybuf);
 321                 free(binkeybuf);
 322                 return (0);
 323         }
 324         (void) bin2hex(binkeybytes, (unsigned char *) binkeybuf, hexkeybuf);
 325         free(binkeybuf);
 326         *encrypted_secret = hexkeybuf;
 327         return (1);






 328 }
 329 
 330 /*
 331  * Generic key len and alg type for version of xdecrypt.
 332  *
 333  * Decrypt secret key using passwd.  The decrypted secret key
 334  * *overwrites* the supplied encrypted secret key.
 335  * The secret key is passed and returned in hex notation.
 336  * Once again, the length is a multiple of 16 hex digits.
 337  *
 338  * If 'do_chksum' is TRUE, the 'secret' buffer is assumed to contain
 339  * a checksum calculated by a call to xencrypt_g().
 340  *
 341  * If keylen is 192 and algtype is 0, then decrypt the same way
 342  * as xdecrypt().
 343  *
 344  * Arg netname can be NULL for 192-0.
 345  */
 346 int
 347 xdecrypt_g(
 348         char *secret,           /* out  */
 349         int keylen,             /* in  */
 350         int algtype,            /* in  */
 351         const char *passwd,     /* in  */
 352         const char netname[],   /* in  */
 353         bool_t do_chksum)       /* in  */
 354 {

 355         des_block key;
 356         char ivec[8];
 357         char *buf;
 358         int err;
 359         int len;
 360         const int classic_des = keylen == 192 && algtype == 0;
 361         const int hexkeybytes = BITS2NIBBLES(keylen);
 362         const int keychecksumsize = classic_des ? KEYCHECKSUMSIZE : MD5HEXSIZE;
 363 
 364         len = (int)strlen(secret) / 2;
 365         if (len > MAX_KEY_CRYPT_LEN)
 366                 return (0);
 367         if ((buf = malloc((unsigned)len)) == 0)
 368                 return (0);
 369 
 370         (void) hex2bin(len, secret, buf);
 371         if (classic_des)
 372                 (void) passwd2des((char *)passwd, key.c);
 373         else
 374                 if (netname)


 402 
 403                         MD5Init(&md5_ctx);
 404                         MD5Update(&md5_ctx, (unsigned char *)secret,
 405                                         hexkeybytes);
 406                         MD5Final(digest, &md5_ctx);
 407 
 408                         /* convert md5 binary digest to hex */
 409                         (void) bin2hex(MD5HEXSIZE/2, digest, md5hexbuf);
 410 
 411                         /* does the digest match the appended one? */
 412                         if (memcmp(&(secret[hexkeybytes]),
 413                                         md5hexbuf, MD5HEXSIZE) != 0) {
 414                                 secret[0] = 0;
 415                                 return (0);
 416                         }
 417                 }
 418 
 419         secret[hexkeybytes] = '\0';
 420 
 421         return (1);






 422 }
 423 
 424 
 425 /*
 426  * Modified version of passwd2des(). passwd2des_g() uses the Kerberos
 427  * RFC 1510 algorithm to generate a DES key from a user password
 428  * and mix-in string. The mix-in is expected to be the netname.
 429  * This function to be used only for extended Diffie-Hellman keys.
 430  *
 431  * If altarg is TRUE, reverse the concat of passwd and mix-in.
 432  */
 433 int
 434 passwd2des_g(
 435         const char *pw,
 436         const char *mixin,
 437         int len,
 438         des_block *key, /* out */
 439         bool_t altalg)
 440 {
 441