1/* 2 * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.crypto.provider; 27 28import java.util.Arrays; 29import java.io.*; 30import java.security.*; 31import javax.crypto.*; 32import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE; 33 34/** 35 * This class represents ciphers in GaloisCounter (GCM) mode. 36 * 37 * <p>This mode currently should only be used w/ AES cipher. 38 * Although no checking is done, caller should only pass AES 39 * Cipher to the constructor. 40 * 41 * <p>NOTE: Unlike other modes, when used for decryption, this class 42 * will buffer all processed outputs internally and won't return them 43 * until the tag has been successfully verified. 44 * 45 * @since 1.8 46 */ 47final class GaloisCounterMode extends FeedbackCipher { 48 49 static int DEFAULT_TAG_LEN = AES_BLOCK_SIZE; 50 static int DEFAULT_IV_LEN = 12; // in bytes 51 52 // In NIST SP 800-38D, GCM input size is limited to be no longer 53 // than (2^36 - 32) bytes. Otherwise, the counter will wrap 54 // around and lead to a leak of plaintext. 55 // However, given the current GCM spec requirement that recovered 56 // text can only be returned after successful tag verification, 57 // we are bound by limiting the data size to the size limit of 58 // java byte array, e.g. Integer.MAX_VALUE, since all data 59 // can only be returned by the doFinal(...) call. 60 private static final int MAX_BUF_SIZE = Integer.MAX_VALUE; 61 62 // buffer for AAD data; if null, meaning update has been called 63 private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); 64 private int sizeOfAAD = 0; 65 66 // buffer for storing input in decryption, not used for encryption 67 private ByteArrayOutputStream ibuffer = null; 68 69 // in bytes; need to convert to bits (default value 128) when needed 70 private int tagLenBytes = DEFAULT_TAG_LEN; 71 72 // these following 2 fields can only be initialized after init() is 73 // called, e.g. after cipher key k is set, and STAY UNCHANGED 74 private byte[] subkeyH = null; 75 private byte[] preCounterBlock = null; 76 77 private GCTR gctrPAndC = null; 78 private GHASH ghashAllToS = null; 79 80 // length of total data, i.e. len(C) 81 private int processed = 0; 82 83 // additional variables for save/restore calls 84 private byte[] aadBufferSave = null; 85 private int sizeOfAADSave = 0; 86 private byte[] ibufferSave = null; 87 private int processedSave = 0; 88 89 // value must be 16-byte long; used by GCTR and GHASH as well 90 static void increment32(byte[] value) { 91 if (value.length != AES_BLOCK_SIZE) { 92 // should never happen 93 throw new ProviderException("Illegal counter block length"); 94 } 95 // start from last byte and only go over 4 bytes, i.e. total 32 bits 96 int n = value.length - 1; 97 while ((n >= value.length - 4) && (++value[n] == 0)) { 98 n--; 99 } 100 } 101 102 private static byte[] getLengthBlock(int ivLenInBytes) { 103 long ivLen = ((long)ivLenInBytes) << 3; 104 byte[] out = new byte[AES_BLOCK_SIZE]; 105 out[8] = (byte)(ivLen >>> 56); 106 out[9] = (byte)(ivLen >>> 48); 107 out[10] = (byte)(ivLen >>> 40); 108 out[11] = (byte)(ivLen >>> 32); 109 out[12] = (byte)(ivLen >>> 24); 110 out[13] = (byte)(ivLen >>> 16); 111 out[14] = (byte)(ivLen >>> 8); 112 out[15] = (byte)ivLen; 113 return out; 114 } 115 116 private static byte[] getLengthBlock(int aLenInBytes, int cLenInBytes) { 117 long aLen = ((long)aLenInBytes) << 3; 118 long cLen = ((long)cLenInBytes) << 3; 119 byte[] out = new byte[AES_BLOCK_SIZE]; 120 out[0] = (byte)(aLen >>> 56); 121 out[1] = (byte)(aLen >>> 48); 122 out[2] = (byte)(aLen >>> 40); 123 out[3] = (byte)(aLen >>> 32); 124 out[4] = (byte)(aLen >>> 24); 125 out[5] = (byte)(aLen >>> 16); 126 out[6] = (byte)(aLen >>> 8); 127 out[7] = (byte)aLen; 128 out[8] = (byte)(cLen >>> 56); 129 out[9] = (byte)(cLen >>> 48); 130 out[10] = (byte)(cLen >>> 40); 131 out[11] = (byte)(cLen >>> 32); 132 out[12] = (byte)(cLen >>> 24); 133 out[13] = (byte)(cLen >>> 16); 134 out[14] = (byte)(cLen >>> 8); 135 out[15] = (byte)cLen; 136 return out; 137 } 138 139 private static byte[] expandToOneBlock(byte[] in, int inOfs, int len) { 140 if (len > AES_BLOCK_SIZE) { 141 throw new ProviderException("input " + len + " too long"); 142 } 143 if (len == AES_BLOCK_SIZE && inOfs == 0) { 144 return in; 145 } else { 146 byte[] paddedIn = new byte[AES_BLOCK_SIZE]; 147 System.arraycopy(in, inOfs, paddedIn, 0, len); 148 return paddedIn; 149 } 150 } 151 152 private static byte[] getJ0(byte[] iv, byte[] subkeyH) { 153 byte[] j0; 154 if (iv.length == 12) { // 96 bits 155 j0 = expandToOneBlock(iv, 0, iv.length); 156 j0[AES_BLOCK_SIZE - 1] = 1; 157 } else { 158 GHASH g = new GHASH(subkeyH); 159 int lastLen = iv.length % AES_BLOCK_SIZE; 160 if (lastLen != 0) { 161 g.update(iv, 0, iv.length - lastLen); 162 byte[] padded = 163 expandToOneBlock(iv, iv.length - lastLen, lastLen); 164 g.update(padded); 165 } else { 166 g.update(iv); 167 } 168 byte[] lengthBlock = getLengthBlock(iv.length); 169 g.update(lengthBlock); 170 j0 = g.digest(); 171 } 172 return j0; 173 } 174 175 private static void checkDataLength(int processed, int len) { 176 if (processed > MAX_BUF_SIZE - len) { 177 throw new ProviderException("SunJCE provider only supports " + 178 "input size up to " + MAX_BUF_SIZE + " bytes"); 179 } 180 } 181 182 GaloisCounterMode(SymmetricCipher embeddedCipher) { 183 super(embeddedCipher); 184 aadBuffer = new ByteArrayOutputStream(); 185 } 186 187 /** 188 * Gets the name of the feedback mechanism 189 * 190 * @return the name of the feedback mechanism 191 */ 192 String getFeedback() { 193 return "GCM"; 194 } 195 196 /** 197 * Resets the cipher object to its original state. 198 * This is used when doFinal is called in the Cipher class, so that the 199 * cipher can be reused (with its original key and iv). 200 */ 201 void reset() { 202 if (aadBuffer == null) { 203 aadBuffer = new ByteArrayOutputStream(); 204 } else { 205 aadBuffer.reset(); 206 } 207 if (gctrPAndC != null) gctrPAndC.reset(); 208 if (ghashAllToS != null) ghashAllToS.reset(); 209 processed = 0; 210 sizeOfAAD = 0; 211 if (ibuffer != null) { 212 ibuffer.reset(); 213 } 214 } 215 216 /** 217 * Save the current content of this cipher. 218 */ 219 void save() { 220 processedSave = processed; 221 sizeOfAADSave = sizeOfAAD; 222 aadBufferSave = 223 ((aadBuffer == null || aadBuffer.size() == 0)? 224 null : aadBuffer.toByteArray()); 225 if (gctrPAndC != null) gctrPAndC.save(); 226 if (ghashAllToS != null) ghashAllToS.save(); 227 if (ibuffer != null) { 228 ibufferSave = ibuffer.toByteArray(); 229 } 230 } 231 232 /** 233 * Restores the content of this cipher to the previous saved one. 234 */ 235 void restore() { 236 processed = processedSave; 237 sizeOfAAD = sizeOfAADSave; 238 if (aadBuffer != null) { 239 aadBuffer.reset(); 240 if (aadBufferSave != null) { 241 aadBuffer.write(aadBufferSave, 0, aadBufferSave.length); 242 } 243 } 244 if (gctrPAndC != null) gctrPAndC.restore(); 245 if (ghashAllToS != null) ghashAllToS.restore(); 246 if (ibuffer != null) { 247 ibuffer.reset(); 248 ibuffer.write(ibufferSave, 0, ibufferSave.length); 249 } 250 } 251 252 /** 253 * Initializes the cipher in the specified mode with the given key 254 * and iv. 255 * 256 * @param decrypting flag indicating encryption or decryption 257 * @param algorithm the algorithm name 258 * @param key the key 259 * @param iv the iv 260 * @param tagLenBytes the length of tag in bytes 261 * 262 * @exception InvalidKeyException if the given key is inappropriate for 263 * initializing this cipher 264 */ 265 void init(boolean decrypting, String algorithm, byte[] key, byte[] iv) 266 throws InvalidKeyException { 267 init(decrypting, algorithm, key, iv, DEFAULT_TAG_LEN); 268 } 269 270 /** 271 * Initializes the cipher in the specified mode with the given key 272 * and iv. 273 * 274 * @param decrypting flag indicating encryption or decryption 275 * @param algorithm the algorithm name 276 * @param key the key 277 * @param iv the iv 278 * @param tagLenBytes the length of tag in bytes 279 * 280 * @exception InvalidKeyException if the given key is inappropriate for 281 * initializing this cipher 282 */ 283 void init(boolean decrypting, String algorithm, byte[] keyValue, 284 byte[] ivValue, int tagLenBytes) 285 throws InvalidKeyException { 286 if (keyValue == null || ivValue == null) { 287 throw new InvalidKeyException("Internal error"); 288 } 289 290 // always encrypt mode for embedded cipher 291 this.embeddedCipher.init(false, algorithm, keyValue); 292 this.subkeyH = new byte[AES_BLOCK_SIZE]; 293 this.embeddedCipher.encryptBlock(new byte[AES_BLOCK_SIZE], 0, 294 this.subkeyH, 0); 295 296 this.iv = ivValue.clone(); 297 preCounterBlock = getJ0(iv, subkeyH); 298 byte[] j0Plus1 = preCounterBlock.clone(); 299 increment32(j0Plus1); 300 gctrPAndC = new GCTR(embeddedCipher, j0Plus1); 301 ghashAllToS = new GHASH(subkeyH); 302 303 this.tagLenBytes = tagLenBytes; 304 if (aadBuffer == null) { 305 aadBuffer = new ByteArrayOutputStream(); 306 } else { 307 aadBuffer.reset(); 308 } 309 processed = 0; 310 sizeOfAAD = 0; 311 if (decrypting) { 312 ibuffer = new ByteArrayOutputStream(); 313 } 314 } 315 316 /** 317 * Continues a multi-part update of the Additional Authentication 318 * Data (AAD), using a subset of the provided buffer. If this 319 * cipher is operating in either GCM or CCM mode, all AAD must be 320 * supplied before beginning operations on the ciphertext (via the 321 * {@code update} and {@code doFinal} methods). 322 * <p> 323 * NOTE: Given most modes do not accept AAD, default impl for this 324 * method throws IllegalStateException. 325 * 326 * @param src the buffer containing the AAD 327 * @param offset the offset in {@code src} where the AAD input starts 328 * @param len the number of AAD bytes 329 * 330 * @throws IllegalStateException if this cipher is in a wrong state 331 * (e.g., has not been initialized), does not accept AAD, or if 332 * operating in either GCM or CCM mode and one of the {@code update} 333 * methods has already been called for the active 334 * encryption/decryption operation 335 * @throws UnsupportedOperationException if this method 336 * has not been overridden by an implementation 337 * 338 * @since 1.8 339 */ 340 void updateAAD(byte[] src, int offset, int len) { 341 if (aadBuffer != null) { 342 aadBuffer.write(src, offset, len); 343 } else { 344 // update has already been called 345 throw new IllegalStateException 346 ("Update has been called; no more AAD data"); 347 } 348 } 349 350 // Feed the AAD data to GHASH, pad if necessary 351 void processAAD() { 352 if (aadBuffer != null) { 353 if (aadBuffer.size() > 0) { 354 byte[] aad = aadBuffer.toByteArray(); 355 sizeOfAAD = aad.length; 356 357 int lastLen = aad.length % AES_BLOCK_SIZE; 358 if (lastLen != 0) { 359 ghashAllToS.update(aad, 0, aad.length - lastLen); 360 byte[] padded = expandToOneBlock(aad, aad.length - lastLen, 361 lastLen); 362 ghashAllToS.update(padded); 363 } else { 364 ghashAllToS.update(aad); 365 } 366 } 367 aadBuffer = null; 368 } 369 } 370 371 // Utility to process the last block; used by encryptFinal and decryptFinal 372 void doLastBlock(byte[] in, int inOfs, int len, byte[] out, int outOfs, 373 boolean isEncrypt) throws IllegalBlockSizeException { 374 // process data in 'in' 375 gctrPAndC.doFinal(in, inOfs, len, out, outOfs); 376 processed += len; 377 378 byte[] ct; 379 int ctOfs; 380 if (isEncrypt) { 381 ct = out; 382 ctOfs = outOfs; 383 } else { 384 ct = in; 385 ctOfs = inOfs; 386 } 387 int lastLen = len % AES_BLOCK_SIZE; 388 if (lastLen != 0) { 389 ghashAllToS.update(ct, ctOfs, len - lastLen); 390 byte[] padded = 391 expandToOneBlock(ct, (ctOfs + len - lastLen), lastLen); 392 ghashAllToS.update(padded); 393 } else { 394 ghashAllToS.update(ct, ctOfs, len); 395 } 396 } 397 398 399 /** 400 * Performs encryption operation. 401 * 402 * <p>The input plain text <code>in</code>, starting at <code>inOff</code> 403 * and ending at <code>(inOff + len - 1)</code>, is encrypted. The result 404 * is stored in <code>out</code>, starting at <code>outOfs</code>. 405 * 406 * @param in the buffer with the input data to be encrypted 407 * @param inOfs the offset in <code>in</code> 408 * @param len the length of the input data 409 * @param out the buffer for the result 410 * @param outOfs the offset in <code>out</code> 411 * @exception ProviderException if <code>len</code> is not 412 * a multiple of the block size 413 * @return the number of bytes placed into the <code>out</code> buffer 414 */ 415 int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) { 416 if ((len % blockSize) != 0) { 417 throw new ProviderException("Internal error in input buffering"); 418 } 419 420 checkDataLength(processed, len); 421 422 processAAD(); 423 if (len > 0) { 424 gctrPAndC.update(in, inOfs, len, out, outOfs); 425 processed += len; 426 ghashAllToS.update(out, outOfs, len); 427 } 428 return len; 429 } 430 431 /** 432 * Performs encryption operation for the last time. 433 * 434 * @param in the input buffer with the data to be encrypted 435 * @param inOfs the offset in <code>in</code> 436 * @param len the length of the input data 437 * @param out the buffer for the encryption result 438 * @param outOfs the offset in <code>out</code> 439 * @return the number of bytes placed into the <code>out</code> buffer 440 */ 441 int encryptFinal(byte[] in, int inOfs, int len, byte[] out, int outOfs) 442 throws IllegalBlockSizeException, ShortBufferException { 443 if (len > MAX_BUF_SIZE - tagLenBytes) { 444 throw new ShortBufferException 445 ("Can't fit both data and tag into one buffer"); 446 } 447 if (out.length - outOfs < (len + tagLenBytes)) { 448 throw new ShortBufferException("Output buffer too small"); 449 } 450 451 checkDataLength(processed, len); 452 453 processAAD(); 454 if (len > 0) { 455 doLastBlock(in, inOfs, len, out, outOfs, true); 456 } 457 458 byte[] lengthBlock = 459 getLengthBlock(sizeOfAAD, processed); 460 ghashAllToS.update(lengthBlock); 461 byte[] s = ghashAllToS.digest(); 462 byte[] sOut = new byte[s.length]; 463 GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock); 464 gctrForSToTag.doFinal(s, 0, s.length, sOut, 0); 465 466 System.arraycopy(sOut, 0, out, (outOfs + len), tagLenBytes); 467 return (len + tagLenBytes); 468 } 469 470 /** 471 * Performs decryption operation. 472 * 473 * <p>The input cipher text <code>in</code>, starting at 474 * <code>inOfs</code> and ending at <code>(inOfs + len - 1)</code>, 475 * is decrypted. The result is stored in <code>out</code>, starting at 476 * <code>outOfs</code>. 477 * 478 * @param in the buffer with the input data to be decrypted 479 * @param inOfs the offset in <code>in</code> 480 * @param len the length of the input data 481 * @param out the buffer for the result 482 * @param outOfs the offset in <code>out</code> 483 * @exception ProviderException if <code>len</code> is not 484 * a multiple of the block size 485 * @return the number of bytes placed into the <code>out</code> buffer 486 */ 487 int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) { 488 if ((len % blockSize) != 0) { 489 throw new ProviderException("Internal error in input buffering"); 490 } 491 492 checkDataLength(ibuffer.size(), len); 493 494 processAAD(); 495 496 if (len > 0) { 497 // store internally until decryptFinal is called because 498 // spec mentioned that only return recovered data after tag 499 // is successfully verified 500 ibuffer.write(in, inOfs, len); 501 } 502 return 0; 503 } 504 505 /** 506 * Performs decryption operation for the last time. 507 * 508 * <p>NOTE: For cipher feedback modes which does not perform 509 * special handling for the last few blocks, this is essentially 510 * the same as <code>encrypt(...)</code>. Given most modes do 511 * not do special handling, the default impl for this method is 512 * to simply call <code>decrypt(...)</code>. 513 * 514 * @param in the input buffer with the data to be decrypted 515 * @param inOfs the offset in <code>cipher</code> 516 * @param len the length of the input data 517 * @param out the buffer for the decryption result 518 * @param outOfs the offset in <code>plain</code> 519 * @return the number of bytes placed into the <code>out</code> buffer 520 */ 521 int decryptFinal(byte[] in, int inOfs, int len, 522 byte[] out, int outOfs) 523 throws IllegalBlockSizeException, AEADBadTagException, 524 ShortBufferException { 525 if (len < tagLenBytes) { 526 throw new AEADBadTagException("Input too short - need tag"); 527 } 528 // do this check here can also catch the potential integer overflow 529 // scenario for the subsequent output buffer capacity check. 530 checkDataLength(ibuffer.size(), (len - tagLenBytes)); 531 532 if (out.length - outOfs < ((ibuffer.size() + len) - tagLenBytes)) { 533 throw new ShortBufferException("Output buffer too small"); 534 } 535 536 processAAD(); 537 538 // get the trailing tag bytes from 'in' 539 byte[] tag = new byte[tagLenBytes]; 540 System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes); 541 len -= tagLenBytes; 542 543 if (len != 0) { 544 ibuffer.write(in, inOfs, len); 545 } 546 547 // refresh 'in' to all buffered-up bytes 548 in = ibuffer.toByteArray(); 549 inOfs = 0; 550 len = in.length; 551 ibuffer.reset(); 552 553 if (len > 0) { 554 doLastBlock(in, inOfs, len, out, outOfs, false); 555 } 556 557 byte[] lengthBlock = 558 getLengthBlock(sizeOfAAD, processed); 559 ghashAllToS.update(lengthBlock); 560 561 byte[] s = ghashAllToS.digest(); 562 byte[] sOut = new byte[s.length]; 563 GCTR gctrForSToTag = new GCTR(embeddedCipher, this.preCounterBlock); 564 gctrForSToTag.doFinal(s, 0, s.length, sOut, 0); 565 566 // check entire authentication tag for time-consistency 567 int mismatch = 0; 568 for (int i = 0; i < tagLenBytes; i++) { 569 mismatch |= tag[i] ^ sOut[i]; 570 } 571 572 if (mismatch != 0) { 573 throw new AEADBadTagException("Tag mismatch!"); 574 } 575 576 return len; 577 } 578 579 // return tag length in bytes 580 int getTagLen() { 581 return this.tagLenBytes; 582 } 583 584 int getBufferedLength() { 585 if (ibuffer == null) { 586 return 0; 587 } else { 588 return ibuffer.size(); 589 } 590 } 591} 592