1 /*
   2  * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 
   5 /*
   6  * Copyright (C) 1998 by the FundsXpress, INC.
   7  *
   8  * All rights reserved.
   9  *
  10  * Export of this software from the United States of America may require
  11  * a specific license from the United States Government.  It is the
  12  * responsibility of any person or organization contemplating export to
  13  * obtain such a license before exporting.
  14  *
  15  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  16  * distribute this software and its documentation for any purpose and
  17  * without fee is hereby granted, provided that the above copyright
  18  * notice appear in all copies and that both that copyright notice and
  19  * this permission notice appear in supporting documentation, and that
  20  * the name of FundsXpress. not be used in advertising or publicity pertaining
  21  * to distribution of the software without specific, written prior
  22  * permission.  FundsXpress makes no representations about the suitability of
  23  * this software for any purpose.  It is provided "as is" without express
  24  * or implied warranty.
  25  *
  26  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  27  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  28  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  29  */
  30 
  31 package sun.security.krb5.internal.crypto.dk;
  32 
  33 import javax.crypto.Cipher;
  34 import javax.crypto.Mac;
  35 import java.security.GeneralSecurityException;
  36 import java.io.UnsupportedEncodingException;
  37 import java.util.Arrays;
  38 import java.io.ByteArrayInputStream;
  39 import java.io.ByteArrayOutputStream;
  40 import java.nio.charset.Charset;
  41 import java.nio.CharBuffer;
  42 import java.nio.ByteBuffer;
  43 import sun.misc.HexDumpEncoder;
  44 import sun.security.krb5.Confounder;
  45 import sun.security.krb5.internal.crypto.KeyUsage;
  46 import sun.security.krb5.KrbCryptoException;
  47 
  48 /**
  49  * Implements Derive Key cryptography functionality as defined in RFC 3961.
  50  * http://www.ietf.org/rfc/rfc3961.txt
  51  *
  52  * This is an abstract class. Concrete subclasses need to implement
  53  * the abstract methods.
  54  */
  55 
  56 public abstract class DkCrypto {
  57 
  58     protected static final boolean debug = false;
  59 
  60     // These values correspond to the ASCII encoding for the string "kerberos"
  61     static final byte[] KERBEROS_CONSTANT =
  62         {0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73};
  63 
  64     protected abstract int getKeySeedLength();  // in bits
  65 
  66     protected abstract byte[] randomToKey(byte[] in);
  67 
  68     protected abstract Cipher getCipher(byte[] key, byte[] ivec, int mode)
  69         throws GeneralSecurityException;
  70 
  71     public abstract int getChecksumLength();  // in bytes
  72 
  73     protected abstract byte[] getHmac(byte[] key, byte[] plaintext)
  74         throws GeneralSecurityException;
  75 
  76     /**
  77      * From RFC 3961.
  78      *
  79      * encryption function       conf = random string of length c
  80      *                     pad = shortest string to bring confounder
  81      *                           and plaintext to a length that's a
  82      *                           multiple of m
  83      *                     (C1, newIV) = E(Ke, conf | plaintext | pad,
  84      *                                     oldstate.ivec)
  85      *                    H1 = HMAC(Ki, conf | plaintext | pad)
  86      *                     ciphertext =  C1 | H1[1..h]
  87      *                     newstate.ivec = newIV
  88      *
  89      * @param ivec initial vector to use when initializing the cipher; if null,
  90      *     then blocksize number of zeros are used,
  91      * @param new_ivec if non-null, it is updated upon return to be the
  92      *       new ivec to use when calling encrypt next time
  93      */
  94     public byte[] encrypt(byte[] baseKey, int usage,
  95         byte[] ivec, byte[] new_ivec, byte[] plaintext, int start, int len)
  96         throws GeneralSecurityException, KrbCryptoException {
  97 
  98         if (!KeyUsage.isValid(usage)) {
  99             throw new GeneralSecurityException("Invalid key usage number: "
 100                                                 + usage);
 101         }
 102 
 103         byte[] Ke = null;
 104         byte[] Ki = null;
 105 
 106         try {
 107             // Derive encryption key
 108 
 109             byte[] constant = new byte[5];
 110             constant[0] = (byte) ((usage>>24)&0xff);
 111             constant[1] = (byte) ((usage>>16)&0xff);
 112             constant[2] = (byte) ((usage>>8)&0xff);
 113             constant[3] = (byte) (usage&0xff);
 114 
 115             constant[4] = (byte) 0xaa;
 116 
 117             Ke = dk(baseKey, constant);
 118             if (debug) {
 119                 System.err.println("usage: " + usage);
 120                 if (ivec != null) {
 121                     traceOutput("old_state.ivec", ivec, 0, ivec.length);
 122                 }
 123                 traceOutput("plaintext", plaintext, start, Math.min(len, 32));
 124                 traceOutput("constant", constant, 0, constant.length);
 125                 traceOutput("baseKey", baseKey, 0, baseKey.length);
 126                 traceOutput("Ke", Ke, 0, Ke.length);
 127             }
 128 
 129             // Encrypt
 130             // C1 = E(Ke, conf | plaintext | pad, oldivec)
 131             Cipher encCipher = getCipher(Ke, ivec, Cipher.ENCRYPT_MODE);
 132             int blockSize = encCipher.getBlockSize();
 133             byte[] confounder = Confounder.bytes(blockSize);
 134 
 135             int plainSize = roundup(confounder.length + len, blockSize);
 136             if (debug) {
 137                 System.err.println("confounder = " + confounder.length +
 138                     "; plaintext = " + len + "; padding = " +
 139                     (plainSize - confounder.length - len) + "; total = " +
 140                         plainSize);
 141                 traceOutput("confounder", confounder, 0, confounder.length);
 142             }
 143 
 144             byte[] toBeEncrypted = new byte[plainSize];
 145             System.arraycopy(confounder, 0, toBeEncrypted,
 146                                 0, confounder.length);
 147             System.arraycopy(plaintext, start, toBeEncrypted,
 148                                 confounder.length, len);
 149 
 150             // Set padding bytes to zero
 151             Arrays.fill(toBeEncrypted, confounder.length + len, plainSize,
 152                         (byte)0);
 153 
 154             int cipherSize = encCipher.getOutputSize(plainSize);
 155             int ccSize =  cipherSize + getChecksumLength();  // cipher | hmac
 156 
 157             byte[] ciphertext = new byte[ccSize];
 158 
 159             encCipher.doFinal(toBeEncrypted, 0, plainSize, ciphertext, 0);
 160 
 161             // Update ivec for next operation
 162             // (last blockSize bytes of ciphertext)
 163             // newstate.ivec = newIV
 164             if (new_ivec != null && new_ivec.length == blockSize) {
 165                 System.arraycopy(ciphertext,  cipherSize - blockSize,
 166                     new_ivec, 0, blockSize);
 167                 if (debug) {
 168                     traceOutput("new_ivec", new_ivec, 0, new_ivec.length);
 169                 }
 170             }
 171 
 172             // Derive integrity key
 173             constant[4] = (byte) 0x55;
 174             Ki = dk(baseKey, constant);
 175             if (debug) {
 176                 traceOutput("constant", constant, 0, constant.length);
 177                 traceOutput("Ki", Ki, 0, Ke.length);
 178             }
 179 
 180             // Generate checksum
 181             // H1 = HMAC(Ki, conf | plaintext | pad)
 182             byte[] hmac = getHmac(Ki, toBeEncrypted);
 183 
 184             if (debug) {
 185                 traceOutput("hmac", hmac, 0, hmac.length);
 186                 traceOutput("ciphertext", ciphertext, 0,
 187                                 Math.min(ciphertext.length, 32));
 188             }
 189 
 190             // C1 | H1[1..h]
 191             System.arraycopy(hmac, 0, ciphertext, cipherSize,
 192                                 getChecksumLength());
 193             return ciphertext;
 194         } finally {
 195             if (Ke != null) {
 196                 Arrays.fill(Ke, 0, Ke.length, (byte) 0);
 197             }
 198             if (Ki != null) {
 199                 Arrays.fill(Ki, 0, Ki.length, (byte) 0);
 200             }
 201         }
 202     }
 203 
 204     /**
 205      * Performs encryption using given key only; does not add
 206      * confounder, padding, or checksum. Incoming data to be encrypted
 207      * assumed to have the correct blocksize.
 208      * Ignore key usage.
 209      */
 210     public byte[] encryptRaw(byte[] baseKey, int usage,
 211         byte[] ivec, byte[] plaintext, int start, int len)
 212         throws GeneralSecurityException, KrbCryptoException {
 213 
 214         if (debug) {
 215             System.err.println("usage: " + usage);
 216             if (ivec != null) {
 217                 traceOutput("old_state.ivec", ivec, 0, ivec.length);
 218             }
 219             traceOutput("plaintext", plaintext, start, Math.min(len, 32));
 220             traceOutput("baseKey", baseKey, 0, baseKey.length);
 221         }
 222 
 223         // Encrypt
 224         Cipher encCipher = getCipher(baseKey, ivec, Cipher.ENCRYPT_MODE);
 225         int blockSize = encCipher.getBlockSize();
 226 
 227         if ((len % blockSize) != 0) {
 228             throw new GeneralSecurityException(
 229                 "length of data to be encrypted (" + len +
 230                 ") is not a multiple of the blocksize (" + blockSize + ")");
 231         }
 232 
 233         int cipherSize = encCipher.getOutputSize(len);
 234         byte[] ciphertext = new byte[cipherSize];
 235 
 236         encCipher.doFinal(plaintext, 0, len, ciphertext, 0);
 237         return ciphertext;
 238     }
 239 
 240     /**
 241      * Decrypts data using specified key and initial vector.
 242      * @param baseKey encryption key to use
 243      * @param ciphertext  encrypted data to be decrypted
 244      * @param usage ignored
 245      */
 246     public byte[] decryptRaw(byte[] baseKey, int usage, byte[] ivec,
 247         byte[] ciphertext, int start, int len)
 248         throws GeneralSecurityException {
 249 
 250         if (debug) {
 251             System.err.println("usage: " + usage);
 252             if (ivec != null) {
 253                 traceOutput("old_state.ivec", ivec, 0, ivec.length);
 254             }
 255             traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
 256             traceOutput("baseKey", baseKey, 0, baseKey.length);
 257         }
 258 
 259         Cipher decCipher = getCipher(baseKey, ivec, Cipher.DECRYPT_MODE);
 260 
 261         int blockSize = decCipher.getBlockSize();
 262 
 263         if ((len % blockSize) != 0) {
 264             throw new GeneralSecurityException(
 265                 "length of data to be decrypted (" + len +
 266                 ") is not a multiple of the blocksize (" + blockSize + ")");
 267         }
 268 
 269         byte[] decrypted = decCipher.doFinal(ciphertext, start, len);
 270 
 271         if (debug) {
 272             traceOutput("decrypted", decrypted, 0,
 273                 Math.min(decrypted.length, 32));
 274         }
 275 
 276         return decrypted;
 277     }
 278 
 279     /**
 280      * @param baseKey key from which keys are to be derived using usage
 281      * @param ciphertext  E(Ke, conf | plaintext | padding, ivec) | H1[1..h]
 282      */
 283     public byte[] decrypt(byte[] baseKey, int usage, byte[] ivec,
 284         byte[] ciphertext, int start, int len) throws GeneralSecurityException {
 285 
 286         if (!KeyUsage.isValid(usage)) {
 287             throw new GeneralSecurityException("Invalid key usage number: "
 288                                                 + usage);
 289         }
 290 
 291         byte[] Ke = null;
 292         byte[] Ki = null;
 293 
 294         try {
 295             // Derive encryption key
 296             byte[] constant = new byte[5];
 297             constant[0] = (byte) ((usage>>24)&0xff);
 298             constant[1] = (byte) ((usage>>16)&0xff);
 299             constant[2] = (byte) ((usage>>8)&0xff);
 300             constant[3] = (byte) (usage&0xff);
 301 
 302             constant[4] = (byte) 0xaa;
 303 
 304             Ke = dk(baseKey, constant);  // Encryption key
 305 
 306             if (debug) {
 307                 System.err.println("usage: " + usage);
 308                 if (ivec != null) {
 309                     traceOutput("old_state.ivec", ivec, 0, ivec.length);
 310                 }
 311                 traceOutput("ciphertext", ciphertext, start, Math.min(len, 32));
 312                 traceOutput("constant", constant, 0, constant.length);
 313                 traceOutput("baseKey", baseKey, 0, baseKey.length);
 314                 traceOutput("Ke", Ke, 0, Ke.length);
 315             }
 316 
 317             Cipher decCipher = getCipher(Ke, ivec, Cipher.DECRYPT_MODE);
 318             int blockSize = decCipher.getBlockSize();
 319 
 320             // Decrypt [confounder | plaintext | padding] (without checksum)
 321             int cksumSize = getChecksumLength();
 322             int cipherSize = len - cksumSize;
 323             byte[] decrypted = decCipher.doFinal(ciphertext, start, cipherSize);
 324 
 325             if (debug) {
 326                 traceOutput("decrypted", decrypted, 0,
 327                                 Math.min(decrypted.length, 32));
 328             }
 329 
 330             // decrypted = [confounder | plaintext | padding]
 331 
 332             // Derive integrity key
 333             constant[4] = (byte) 0x55;
 334             Ki = dk(baseKey, constant);  // Integrity key
 335             if (debug) {
 336                 traceOutput("constant", constant, 0, constant.length);
 337                 traceOutput("Ki", Ki, 0, Ke.length);
 338             }
 339 
 340             // Verify checksum
 341             // H1 = HMAC(Ki, conf | plaintext | pad)
 342             byte[] calculatedHmac = getHmac(Ki, decrypted);
 343 
 344             if (debug) {
 345                 traceOutput("calculated Hmac", calculatedHmac, 0,
 346                     calculatedHmac.length);
 347                 traceOutput("message Hmac", ciphertext, cipherSize,
 348                     cksumSize);
 349             }
 350 
 351             boolean cksumFailed = false;
 352             if (calculatedHmac.length >= cksumSize) {
 353                 for (int i = 0; i < cksumSize; i++) {
 354                     if (calculatedHmac[i] != ciphertext[cipherSize+i]) {
 355                         cksumFailed = true;
 356                         break;
 357                     }
 358                 }
 359             }
 360 
 361             if (cksumFailed) {
 362                 throw new GeneralSecurityException("Checksum failed");
 363             }
 364 
 365             // Prepare decrypted msg and ivec to be returned
 366             // Last blockSize bytes of ciphertext without checksum
 367             if (ivec != null && ivec.length == blockSize) {
 368                 System.arraycopy(ciphertext,  start + cipherSize - blockSize,
 369                     ivec, 0, blockSize);
 370                 if (debug) {
 371                     traceOutput("new_state.ivec", ivec, 0, ivec.length);
 372                 }
 373             }
 374 
 375             // Get rid of confounder
 376             // [plaintext | padding]
 377             byte[] plaintext = new byte[decrypted.length - blockSize];
 378             System.arraycopy(decrypted, blockSize, plaintext,
 379                                 0, plaintext.length);
 380             return plaintext; // padding still there
 381         } finally {
 382             if (Ke != null) {
 383                 Arrays.fill(Ke, 0, Ke.length, (byte) 0);
 384             }
 385             if (Ki != null) {
 386                 Arrays.fill(Ki, 0, Ki.length, (byte) 0);
 387             }
 388         }
 389     }
 390 
 391     // Round up to the next blocksize
 392     int roundup(int n, int blocksize) {
 393         return (((n + blocksize - 1) / blocksize) * blocksize);
 394     }
 395 
 396     public byte[] calculateChecksum(byte[] baseKey, int usage, byte[] input,
 397         int start, int len) throws GeneralSecurityException {
 398 
 399         if (!KeyUsage.isValid(usage)) {
 400             throw new GeneralSecurityException("Invalid key usage number: "
 401                                                 + usage);
 402         }
 403 
 404         // Derive keys
 405         byte[] constant = new byte[5];
 406         constant[0] = (byte) ((usage>>24)&0xff);
 407         constant[1] = (byte) ((usage>>16)&0xff);
 408         constant[2] = (byte) ((usage>>8)&0xff);
 409         constant[3] = (byte) (usage&0xff);
 410 
 411         constant[4] = (byte) 0x99;
 412 
 413         byte[] Kc = dk(baseKey, constant);  // Checksum key
 414         if (debug) {
 415             System.err.println("usage: " + usage);
 416             traceOutput("input", input, start, Math.min(len, 32));
 417             traceOutput("constant", constant, 0, constant.length);
 418             traceOutput("baseKey", baseKey, 0, baseKey.length);
 419             traceOutput("Kc", Kc, 0, Kc.length);
 420         }
 421 
 422         try {
 423             // Generate checksum
 424             // H1 = HMAC(Kc, input)
 425             byte[] hmac = getHmac(Kc, input);
 426             if (debug) {
 427                 traceOutput("hmac", hmac, 0, hmac.length);
 428             }
 429             if (hmac.length == getChecksumLength()) {
 430                 return hmac;
 431             } else if (hmac.length > getChecksumLength()) {
 432                 byte[] buf = new byte[getChecksumLength()];
 433                 System.arraycopy(hmac, 0, buf, 0, buf.length);
 434                 return buf;
 435             } else {
 436                 throw new GeneralSecurityException("checksum size too short: " +
 437                     hmac.length + "; expecting : " + getChecksumLength());
 438             }
 439         } finally {
 440             Arrays.fill(Kc, 0, Kc.length, (byte)0);
 441         }
 442     }
 443 
 444     // DK(Key, Constant) = random-to-key(DR(Key, Constant))
 445     byte[] dk(byte[] key, byte[] constant)
 446         throws GeneralSecurityException {
 447         return randomToKey(dr(key, constant));
 448     }
 449 
 450     /*
 451      * From RFC 3961.
 452      *
 453      * DR(Key, Constant) = k-truncate(E(Key, Constant,
 454      *                                  initial-cipher-state))
 455      *
 456      * Here DR is the random-octet generation function described below, and
 457      * DK is the key-derivation function produced from it.  In this
 458      * construction, E(Key, Plaintext, CipherState) is a cipher, Constant is
 459      * a well-known constant determined by the specific usage of this
 460      * function, and k-truncate truncates its argument by taking the first k
 461      * bits.  Here, k is the key generation seed length needed for the
 462      * encryption system.
 463      *
 464      * The output of the DR function is a string of bits; the actual key is
 465      * produced by applying the cryptosystem's random-to-key operation on
 466      * this bitstring.
 467      *
 468      * If the Constant is smaller than the cipher block size of E, then it
 469      * must be expanded with n-fold() so it can be encrypted.  If the output
 470      * of E is shorter than k bits it is fed back into the encryption as
 471      * many times as necessary.  The construct is as follows (where |
 472      * indicates concatentation):
 473      *
 474      * K1 = E(Key, n-fold(Constant), initial-cipher-state)
 475      * K2 = E(Key, K1, initial-cipher-state)
 476      * K3 = E(Key, K2, initial-cipher-state)
 477      * K4 = ...
 478      *
 479      * DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)
 480      */
 481     private byte[] dr(byte[] key, byte[] constant)
 482         throws GeneralSecurityException {
 483 
 484         Cipher encCipher = getCipher(key, null, Cipher.ENCRYPT_MODE);
 485         int blocksize = encCipher.getBlockSize();
 486 
 487         if (constant.length != blocksize) {
 488             constant = nfold(constant, blocksize * 8);
 489         }
 490         byte[] toBeEncrypted = constant;
 491 
 492         int keybytes = (getKeySeedLength()>>3);  // from bits to bytes
 493         byte[] rawkey = new byte[keybytes];
 494         int posn = 0;
 495 
 496         /* loop encrypting the blocks until enough key bytes are generated */
 497         int n = 0, len;
 498         while (n < keybytes) {
 499             if (debug) {
 500                 System.err.println("Encrypting: " +
 501                     bytesToString(toBeEncrypted));
 502             }
 503 
 504             byte[] cipherBlock = encCipher.doFinal(toBeEncrypted);
 505             if (debug) {
 506                 System.err.println("K: " + ++posn + " = " +
 507                     bytesToString(cipherBlock));
 508             }
 509 
 510             len = (keybytes - n <= cipherBlock.length ? (keybytes - n) :
 511                 cipherBlock.length);
 512             if (debug) {
 513                 System.err.println("copying " + len + " key bytes");
 514             }
 515             System.arraycopy(cipherBlock, 0, rawkey, n, len);
 516             n += len;
 517             toBeEncrypted = cipherBlock;
 518         }
 519         return rawkey;
 520     }
 521 
 522 // ---------------------------------
 523 
 524     // From MIT-1.3.1 distribution
 525     /*
 526      * n-fold(k-bits):
 527      *   l = lcm(n,k)
 528      *   r = l/k
 529      * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1)
 530      * compute the 1's complement sum:
 531      * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1]
 532      */
 533 
 534     /*
 535      * representation: msb first, assume n and k are multiples of 8, and
 536      *  that k>=16.  this is the case of all the cryptosystems which are
 537      *  likely to be used.  this function can be replaced if that
 538      *  assumption ever fails.
 539      */
 540 
 541     /* input length is in bits */
 542     static byte[] nfold(byte[] in, int outbits) {
 543 
 544         int inbits = in.length;
 545         outbits >>= 3;    // count in bytes
 546 
 547         /* first compute lcm(n,k) */
 548         int a, b, c, lcm;
 549         a = outbits;  // n
 550         b = inbits;   // k
 551 
 552         while (b != 0) {
 553             c = b;
 554             b = a % b;
 555             a = c;
 556         }
 557         lcm = outbits*inbits/a;
 558 
 559         if (debug) {
 560             System.err.println("k: " + inbits);
 561             System.err.println("n: " + outbits);
 562             System.err.println("lcm: " + lcm);
 563         }
 564 
 565         /* now do the real work */
 566         byte[] out = new byte[outbits];
 567         Arrays.fill(out, (byte)0);
 568 
 569         int thisbyte = 0;
 570         int msbit, i, bval, oval;
 571 
 572         // this will end up cycling through k lcm(k,n)/k times, which
 573         // is correct
 574         for (i = lcm-1; i >= 0; i--) {
 575             /* compute the msbit in k which gets added into this byte */
 576             msbit = (/* first, start with msbit in the first, unrotated byte */
 577                 ((inbits<<3)-1)
 578                 /* then, for each byte, shift to right for each repetition */
 579                 + (((inbits<<3)+13)*(i/inbits))
 580                 /* last, pick out correct byte within that shifted repetition */
 581                 + ((inbits-(i%inbits)) << 3)) % (inbits << 3);
 582 
 583             /* pull out the byte value itself */
 584             // Mask off values using &0xff to get only the lower byte
 585             // Use >>> to avoid sign extension
 586             bval =  ((((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)|
 587                 (in[((inbits)-(msbit>>>3))%inbits]&0xff))
 588                 >>>((msbit&7)+1))&0xff;
 589 
 590             /*
 591             System.err.println("((" +
 592                 ((in[((inbits-1)-(msbit>>>3))%inbits]&0xff)<<8)
 593                 + "|" + (in[((inbits)-(msbit>>>3))%inbits]&0xff) + ")"
 594                 + ">>>" + ((msbit&7)+1) + ")&0xff = " + bval);
 595             */
 596 
 597             thisbyte += bval;
 598 
 599             /* do the addition */
 600             // Mask off values using &0xff to get only the lower byte
 601             oval = (out[i%outbits]&0xff);
 602             thisbyte += oval;
 603             out[i%outbits] = (byte) (thisbyte&0xff);
 604 
 605             if (debug) {
 606                 System.err.println("msbit[" + i + "] = " +  msbit + "\tbval=" +
 607                     Integer.toHexString(bval) + "\toval=" +
 608                     Integer.toHexString(oval)
 609                     + "\tsum = " + Integer.toHexString(thisbyte));
 610             }
 611 
 612 
 613             /* keep around the carry bit, if any */
 614             thisbyte >>>= 8;
 615 
 616             if (debug) {
 617                 System.err.println("carry=" + thisbyte);
 618             }
 619         }
 620 
 621         /* if there's a carry bit left over, add it back in */
 622         if (thisbyte != 0) {
 623             for (i = outbits-1; i >= 0; i--) {
 624                 /* do the addition */
 625                 thisbyte += (out[i]&0xff);
 626                 out[i] = (byte) (thisbyte&0xff);
 627 
 628                 /* keep around the carry bit, if any */
 629                 thisbyte >>>= 8;
 630             }
 631         }
 632 
 633         return out;
 634     }
 635 
 636     // Routines used for debugging
 637     static String bytesToString(byte[] digest) {
 638         // Get character representation of digest
 639         StringBuilder digestString = new StringBuilder();
 640 
 641         for (int i = 0; i < digest.length; i++) {
 642             if ((digest[i] & 0x000000ff) < 0x10) {
 643                 digestString.append('0').append(Integer.toHexString(digest[i] & 0x000000ff));
 644             } else {
 645                 digestString.append(
 646                     Integer.toHexString(digest[i] & 0x000000ff));
 647             }
 648         }
 649         return digestString.toString();
 650     }
 651 
 652     private static byte[] binaryStringToBytes(String str) {
 653         char[] usageStr = str.toCharArray();
 654         byte[] usage = new byte[usageStr.length/2];
 655         for (int i = 0; i < usage.length; i++) {
 656             byte a = Byte.parseByte(new String(usageStr, i*2, 1), 16);
 657             byte b = Byte.parseByte(new String(usageStr, i*2 + 1, 1), 16);
 658             usage[i] = (byte) ((a<<4)|b);
 659         }
 660         return usage;
 661     }
 662 
 663     static void traceOutput(String traceTag, byte[] output, int offset,
 664         int len) {
 665         try {
 666             ByteArrayOutputStream out = new ByteArrayOutputStream(len);
 667             new HexDumpEncoder().encodeBuffer(
 668                 new ByteArrayInputStream(output, offset, len), out);
 669 
 670             System.err.println(traceTag + ":" + out.toString());
 671         } catch (Exception e) {
 672         }
 673     }
 674 
 675 // String.getBytes("UTF-8");
 676 // Do this instead of using String to avoid making password immutable
 677     static byte[] charToUtf8(char[] chars) {
 678         Charset utf8 = Charset.forName("UTF-8");
 679 
 680         CharBuffer cb = CharBuffer.wrap(chars);
 681         ByteBuffer bb = utf8.encode(cb);
 682         int len = bb.limit();
 683         byte[] answer = new byte[len];
 684         bb.get(answer, 0, len);
 685         return answer;
 686     }
 687 
 688     static byte[] charToUtf16(char[] chars) {
 689         Charset utf8 = Charset.forName("UTF-16LE");
 690 
 691         CharBuffer cb = CharBuffer.wrap(chars);
 692         ByteBuffer bb = utf8.encode(cb);
 693         int len = bb.limit();
 694         byte[] answer = new byte[len];
 695         bb.get(answer, 0, len);
 696         return answer;
 697     }
 698 }