199 mode == Cipher.DECRYPT_MODE && |
169 mode == Cipher.DECRYPT_MODE && |
200 protocolVersion.v >= ProtocolVersion.TLS11.v) { |
170 protocolVersion.v >= ProtocolVersion.TLS11.v) { |
201 iv = getFixedMask(bulkCipher.ivSize); |
171 iv = getFixedMask(bulkCipher.ivSize); |
202 } |
172 } |
203 |
173 |
204 if (cipherType == AEAD_CIPHER) { |
174 cipher.init(mode, key, iv, random); |
205 // AEAD must completely initialize the cipher for each packet, |
175 |
206 // and so we save initialization parameters for packet |
176 // Do not call getBlockSize until after init() |
207 // processing time. |
177 // otherwise we would disrupt JCE delayed provider selection |
208 |
178 blockSize = cipher.getBlockSize(); |
209 // Set the tag size for AEAD cipher |
179 // some providers implement getBlockSize() incorrectly |
210 tagSize = bulkCipher.tagSize; |
180 if (blockSize == 1) { |
211 |
181 blockSize = 0; |
212 // Reserve the key for AEAD cipher initialization |
|
213 this.key = key; |
|
214 |
|
215 fixedIv = iv.getIV(); |
|
216 if (fixedIv == null || |
|
217 fixedIv.length != bulkCipher.fixedIvSize) { |
|
218 throw new RuntimeException("Improper fixed IV for AEAD"); |
|
219 } |
|
220 |
|
221 // Set the record IV length for AEAD cipher |
|
222 recordIvSize = bulkCipher.ivSize - bulkCipher.fixedIvSize; |
|
223 |
|
224 // DON'T initialize the cipher for AEAD! |
|
225 } else { |
|
226 // CBC only requires one initialization during its lifetime |
|
227 // (future packets/IVs set the proper CBC state), so we can |
|
228 // initialize now. |
|
229 |
|
230 // Zeroize the variables that only apply to AEAD cipher |
|
231 this.tagSize = 0; |
|
232 this.fixedIv = new byte[0]; |
|
233 this.recordIvSize = 0; |
|
234 this.key = null; |
|
235 |
|
236 // Initialize the cipher |
|
237 cipher.init(mode, key, iv, random); |
|
238 } |
182 } |
239 } catch (NoSuchAlgorithmException e) { |
183 } catch (NoSuchAlgorithmException e) { |
240 throw e; |
184 throw e; |
241 } catch (Exception e) { |
185 } catch (Exception e) { |
242 throw new NoSuchAlgorithmException |
186 throw new NoSuchAlgorithmException |
341 * The byte buffers position and limit initially define the amount |
286 * The byte buffers position and limit initially define the amount |
342 * to encrypt. On return, the position and limit are |
287 * to encrypt. On return, the position and limit are |
343 * set to last position padded/encrypted. The limit may have changed |
288 * set to last position padded/encrypted. The limit may have changed |
344 * because of the added padding bytes. |
289 * because of the added padding bytes. |
345 */ |
290 */ |
346 int encrypt(ByteBuffer bb, int outLimit) { |
291 int encrypt(ByteBuffer bb) { |
347 |
292 |
348 int len = bb.remaining(); |
293 int len = bb.remaining(); |
349 |
294 |
350 if (cipher == null) { |
295 if (cipher == null) { |
351 bb.position(bb.limit()); |
296 bb.position(bb.limit()); |
352 return len; |
297 return len; |
353 } |
298 } |
354 |
299 |
355 int pos = bb.position(); |
300 try { |
356 |
301 int pos = bb.position(); |
357 int blockSize = cipher.getBlockSize(); |
302 |
358 if (cipherType == BLOCK_CIPHER) { |
303 if (blockSize != 0) { |
359 // addPadding adjusts pos/limit |
304 // TLSv1.1 needs a IV block |
360 len = addPadding(bb, blockSize); |
305 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { |
361 bb.position(pos); |
306 // generate a random number |
362 } |
307 byte[] prefix = new byte[blockSize]; |
363 |
308 random.nextBytes(prefix); |
364 if (debug != null && Debug.isOn("plaintext")) { |
309 |
365 try { |
310 // move forward the plaintext |
366 HexDumpEncoder hd = new HexDumpEncoder(); |
311 byte[] buf = null; |
367 |
312 int limit = bb.limit(); |
368 System.out.println( |
313 if (bb.hasArray()) { |
369 "Padded plaintext before ENCRYPTION: len = " |
314 int arrayOffset = bb.arrayOffset(); |
370 + len); |
315 buf = bb.array(); |
371 hd.encodeBuffer(bb.duplicate(), System.out); |
316 System.arraycopy(buf, arrayOffset + pos, |
372 |
317 buf, arrayOffset + pos + prefix.length, |
373 } catch (IOException e) { } |
318 limit - pos); |
374 } |
319 bb.limit(limit + prefix.length); |
375 |
320 } else { |
376 /* |
321 buf = new byte[limit - pos]; |
377 * Encrypt "in-place". This does not add its own padding. |
322 bb.get(buf, 0, limit - pos); |
378 */ |
323 bb.position(pos + prefix.length); |
379 ByteBuffer dup = bb.duplicate(); |
324 bb.limit(limit + prefix.length); |
380 if (cipherType == AEAD_CIPHER) { |
325 bb.put(buf); |
381 try { |
|
382 int outputSize = cipher.getOutputSize(dup.remaining()); |
|
383 if (outputSize > bb.remaining()) { |
|
384 // need to expand the limit of the output buffer for |
|
385 // the authentication tag. |
|
386 // |
|
387 // DON'T worry about the buffer's capacity, we have |
|
388 // reserved space for the authentication tag. |
|
389 if (outLimit < pos + outputSize) { |
|
390 // unlikely to happen |
|
391 throw new ShortBufferException( |
|
392 "need more space in output buffer"); |
|
393 } |
326 } |
394 bb.limit(pos + outputSize); |
327 bb.position(pos); |
|
328 |
|
329 // prefix the plaintext |
|
330 bb.put(prefix); |
|
331 bb.position(pos); |
395 } |
332 } |
396 int newLen = cipher.doFinal(dup, bb); |
333 |
397 if (newLen != outputSize) { |
334 // addPadding adjusts pos/limit |
398 throw new RuntimeException( |
335 len = addPadding(bb, blockSize); |
399 "Cipher buffering error in JCE provider " + |
336 bb.position(pos); |
400 cipher.getProvider().getName()); |
337 } |
401 } |
338 if (debug != null && Debug.isOn("plaintext")) { |
402 return newLen; |
339 try { |
403 } catch (IllegalBlockSizeException | |
340 HexDumpEncoder hd = new HexDumpEncoder(); |
404 BadPaddingException | ShortBufferException ibse) { |
341 |
405 // unlikely to happen |
342 System.out.println( |
406 throw new RuntimeException( |
343 "Padded plaintext before ENCRYPTION: len = " |
407 "Cipher error in AEAD mode in JCE provider " + |
344 + len); |
408 cipher.getProvider().getName(), ibse); |
345 hd.encodeBuffer(bb, System.out); |
409 } |
346 |
410 } else { |
347 } catch (IOException e) { } |
411 int newLen; |
348 /* |
412 try { |
349 * reset back to beginning |
413 newLen = cipher.update(dup, bb); |
350 */ |
414 } catch (ShortBufferException sbe) { |
351 bb.position(pos); |
415 // unlikely to happen |
352 } |
416 throw new RuntimeException("Cipher buffering error " + |
353 |
417 "in JCE provider " + cipher.getProvider().getName()); |
354 /* |
418 } |
355 * Encrypt "in-place". This does not add its own padding. |
|
356 */ |
|
357 ByteBuffer dup = bb.duplicate(); |
|
358 int newLen = cipher.update(dup, bb); |
419 |
359 |
420 if (bb.position() != dup.position()) { |
360 if (bb.position() != dup.position()) { |
421 throw new RuntimeException("bytebuffer padding error"); |
361 throw new RuntimeException("bytebuffer padding error"); |
422 } |
362 } |
423 |
363 |
526 /* |
461 /* |
527 * Decrypt "in-place". |
462 * Decrypt "in-place". |
528 */ |
463 */ |
529 int pos = bb.position(); |
464 int pos = bb.position(); |
530 ByteBuffer dup = bb.duplicate(); |
465 ByteBuffer dup = bb.duplicate(); |
531 int newLen; |
466 int newLen = cipher.update(dup, bb); |
532 if (cipherType == AEAD_CIPHER) { |
467 if (newLen != len) { |
533 try { |
468 // catch BouncyCastle buffering error |
534 newLen = cipher.doFinal(dup, bb); |
469 throw new RuntimeException("Cipher buffering error " + |
535 } catch (IllegalBlockSizeException ibse) { |
470 "in JCE provider " + cipher.getProvider().getName()); |
536 // unlikely to happen |
471 } |
537 throw new RuntimeException( |
|
538 "Cipher error in AEAD mode \"" + ibse.getMessage() + |
|
539 " \"in JCE provider " + cipher.getProvider().getName()); |
|
540 } |
|
541 } else { |
|
542 newLen = cipher.update(dup, bb); |
|
543 if (newLen != len) { |
|
544 // catch BouncyCastle buffering error |
|
545 throw new RuntimeException("Cipher buffering error " + |
|
546 "in JCE provider " + cipher.getProvider().getName()); |
|
547 } |
|
548 } |
|
549 |
|
550 // reset the limit to the end of the decryted data |
|
551 bb.limit(pos + newLen); |
|
552 |
472 |
553 if (debug != null && Debug.isOn("plaintext")) { |
473 if (debug != null && Debug.isOn("plaintext")) { |
|
474 bb.position(pos); |
554 try { |
475 try { |
555 HexDumpEncoder hd = new HexDumpEncoder(); |
476 HexDumpEncoder hd = new HexDumpEncoder(); |
556 |
477 |
557 System.out.println( |
478 System.out.println( |
558 "Padded plaintext after DECRYPTION: len = " |
479 "Padded plaintext after DECRYPTION: len = " |
559 + newLen); |
480 + newLen); |
560 |
481 |
561 hd.encodeBuffer( |
482 hd.encodeBuffer(bb, System.out); |
562 (ByteBuffer)bb.duplicate().position(pos), System.out); |
|
563 } catch (IOException e) { } |
483 } catch (IOException e) { } |
564 } |
484 } |
565 |
485 |
566 /* |
486 /* |
567 * Remove the block padding. |
487 * Remove the block padding. |
568 */ |
488 */ |
569 if (cipherType == BLOCK_CIPHER) { |
489 if (blockSize != 0) { |
570 int blockSize = cipher.getBlockSize(); |
|
571 bb.position(pos); |
490 bb.position(pos); |
572 newLen = removePadding(bb, blockSize, protocolVersion); |
491 newLen = removePadding(bb, blockSize, protocolVersion); |
573 |
492 |
574 // check the explicit IV of TLS v1.1 or later |
|
575 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { |
493 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { |
576 if (newLen < blockSize) { |
494 if (newLen < blockSize) { |
577 throw new BadPaddingException("invalid explicit IV"); |
495 throw new BadPaddingException("invalid explicit IV"); |
578 } |
496 } |
579 |
497 |
|
498 // discards the first cipher block, the IV component. |
|
499 byte[] buf = null; |
|
500 int limit = bb.limit(); |
|
501 if (bb.hasArray()) { |
|
502 int arrayOffset = bb.arrayOffset(); |
|
503 buf = bb.array(); |
|
504 System.arraycopy(buf, arrayOffset + pos + blockSize, |
|
505 buf, arrayOffset + pos, limit - pos - blockSize); |
|
506 bb.limit(limit - blockSize); |
|
507 } else { |
|
508 buf = new byte[limit - pos - blockSize]; |
|
509 bb.position(pos + blockSize); |
|
510 bb.get(buf); |
|
511 bb.position(pos); |
|
512 bb.put(buf); |
|
513 bb.limit(limit - blockSize); |
|
514 } |
|
515 |
580 // reset the position to the end of the decrypted data |
516 // reset the position to the end of the decrypted data |
581 bb.position(bb.limit()); |
517 limit = bb.limit(); |
|
518 bb.position(limit); |
582 } |
519 } |
583 } |
520 } |
584 return newLen; |
521 return newLen; |
585 } catch (ShortBufferException e) { |
522 } catch (ShortBufferException e) { |
586 // unlikely to happen, we should have enough buffer space here |
523 RuntimeException exc = new RuntimeException(e.toString()); |
587 throw new ArrayIndexOutOfBoundsException(e.toString()); |
524 exc.initCause(e); |
|
525 throw exc; |
588 } |
526 } |
589 } |
527 } |
590 |
528 |
591 private static int addPadding(byte[] buf, int offset, int len, |
529 private static int addPadding(byte[] buf, int offset, int len, |
592 int blockSize) { |
530 int blockSize) { |
755 try { |
693 try { |
756 if (cipher != null) { |
694 if (cipher != null) { |
757 // ignore return value. |
695 // ignore return value. |
758 cipher.doFinal(); |
696 cipher.doFinal(); |
759 } |
697 } |
760 } catch (Exception e) { |
698 } catch (GeneralSecurityException e) { |
761 // swallow all types of exceptions. |
699 // swallow for now. |
762 } |
700 } |
763 } |
701 } |
764 |
702 |
765 /* |
703 /* |
766 * Does the cipher use CBC mode? |
704 * Does the cipher use CBC mode? |
767 * |
705 * |
768 * @return true if the cipher use CBC mode, false otherwise. |
706 * @return true if the cipher use CBC mode, false otherwise. |
769 */ |
707 */ |
770 boolean isCBCMode() { |
708 boolean isCBCMode() { |
771 return cipherType == BLOCK_CIPHER; |
709 return isCBCMode; |
772 } |
|
773 |
|
774 /* |
|
775 * Does the cipher use AEAD mode? |
|
776 * |
|
777 * @return true if the cipher use AEAD mode, false otherwise. |
|
778 */ |
|
779 boolean isAEADMode() { |
|
780 return cipherType == AEAD_CIPHER; |
|
781 } |
|
782 |
|
783 /* |
|
784 * Is the cipher null? |
|
785 * |
|
786 * @return true if the cipher is null, false otherwise. |
|
787 */ |
|
788 boolean isNullCipher() { |
|
789 return cipher == null; |
|
790 } |
|
791 |
|
792 /* |
|
793 * Gets the explicit nonce/IV size of the cipher. |
|
794 * |
|
795 * The returned value is the SecurityParameters.record_iv_length in |
|
796 * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the |
|
797 * size of explicit nonce for AEAD mode. |
|
798 * |
|
799 * @return the explicit nonce size of the cipher. |
|
800 */ |
|
801 int getExplicitNonceSize() { |
|
802 switch (cipherType) { |
|
803 case BLOCK_CIPHER: |
|
804 // For block ciphers, the explicit IV length is of length |
|
805 // SecurityParameters.record_iv_length, which is equal to |
|
806 // the SecurityParameters.block_size. |
|
807 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { |
|
808 return cipher.getBlockSize(); |
|
809 } |
|
810 break; |
|
811 case AEAD_CIPHER: |
|
812 return recordIvSize; |
|
813 // It is also the length of sequence number, which is |
|
814 // used as the nonce_explicit for AEAD cipher suites. |
|
815 } |
|
816 |
|
817 return 0; |
|
818 } |
|
819 |
|
820 /* |
|
821 * Applies the explicit nonce/IV to this cipher. This method is used to |
|
822 * decrypt an SSL/TLS input record. |
|
823 * |
|
824 * The returned value is the SecurityParameters.record_iv_length in |
|
825 * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the |
|
826 * size of explicit nonce for AEAD mode. |
|
827 * |
|
828 * @param authenticator the authenticator to get the additional |
|
829 * authentication data |
|
830 * @param contentType the content type of the input record |
|
831 * @param bb the byte buffer to get the explicit nonce from |
|
832 * |
|
833 * @return the explicit nonce size of the cipher. |
|
834 */ |
|
835 int applyExplicitNonce(Authenticator authenticator, byte contentType, |
|
836 ByteBuffer bb) throws BadPaddingException { |
|
837 switch (cipherType) { |
|
838 case BLOCK_CIPHER: |
|
839 // For block ciphers, the explicit IV length is of length |
|
840 // SecurityParameters.record_iv_length, which is equal to |
|
841 // the SecurityParameters.block_size. |
|
842 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { |
|
843 return cipher.getBlockSize(); |
|
844 } |
|
845 break; |
|
846 case AEAD_CIPHER: |
|
847 if (bb.remaining() < (recordIvSize + tagSize)) { |
|
848 throw new BadPaddingException( |
|
849 "invalid AEAD cipher fragment"); |
|
850 } |
|
851 |
|
852 // initialize the AEAD cipher for the unique IV |
|
853 byte[] iv = Arrays.copyOf(fixedIv, |
|
854 fixedIv.length + recordIvSize); |
|
855 bb.get(iv, fixedIv.length, recordIvSize); |
|
856 bb.position(bb.position() - recordIvSize); |
|
857 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); |
|
858 try { |
|
859 cipher.init(mode, key, spec, random); |
|
860 } catch (InvalidKeyException | |
|
861 InvalidAlgorithmParameterException ikae) { |
|
862 // unlikely to happen |
|
863 throw new RuntimeException( |
|
864 "invalid key or spec in GCM mode", ikae); |
|
865 } |
|
866 |
|
867 // update the additional authentication data |
|
868 byte[] aad = authenticator.acquireAuthenticationBytes( |
|
869 contentType, bb.remaining() - recordIvSize - tagSize); |
|
870 cipher.updateAAD(aad); |
|
871 |
|
872 return recordIvSize; |
|
873 // It is also the length of sequence number, which is |
|
874 // used as the nonce_explicit for AEAD cipher suites. |
|
875 } |
|
876 |
|
877 return 0; |
|
878 } |
|
879 |
|
880 /* |
|
881 * Applies the explicit nonce/IV to this cipher. This method is used to |
|
882 * decrypt an SSL/TLS input record. |
|
883 * |
|
884 * The returned value is the SecurityParameters.record_iv_length in |
|
885 * RFC 4346/5246. It is the size of explicit IV for CBC mode, and the |
|
886 * size of explicit nonce for AEAD mode. |
|
887 * |
|
888 * @param authenticator the authenticator to get the additional |
|
889 * authentication data |
|
890 * @param contentType the content type of the input record |
|
891 * @param buf the byte array to get the explicit nonce from |
|
892 * @param offset the offset of the byte buffer |
|
893 * @param cipheredLength the ciphered fragment length of the output |
|
894 * record, it is the TLSCiphertext.length in RFC 4346/5246. |
|
895 * |
|
896 * @return the explicit nonce size of the cipher. |
|
897 */ |
|
898 int applyExplicitNonce(Authenticator authenticator, |
|
899 byte contentType, byte[] buf, int offset, |
|
900 int cipheredLength) throws BadPaddingException { |
|
901 |
|
902 ByteBuffer bb = ByteBuffer.wrap(buf, offset, cipheredLength); |
|
903 |
|
904 return applyExplicitNonce(authenticator, contentType, bb); |
|
905 } |
|
906 |
|
907 /* |
|
908 * Creates the explicit nonce/IV to this cipher. This method is used to |
|
909 * encrypt an SSL/TLS output record. |
|
910 * |
|
911 * The size of the returned array is the SecurityParameters.record_iv_length |
|
912 * in RFC 4346/5246. It is the size of explicit IV for CBC mode, and the |
|
913 * size of explicit nonce for AEAD mode. |
|
914 * |
|
915 * @param authenticator the authenticator to get the additional |
|
916 * authentication data |
|
917 * @param contentType the content type of the input record |
|
918 * @param fragmentLength the fragment length of the output record, it is |
|
919 * the TLSCompressed.length in RFC 4346/5246. |
|
920 * |
|
921 * @return the explicit nonce of the cipher. |
|
922 */ |
|
923 byte[] createExplicitNonce(Authenticator authenticator, |
|
924 byte contentType, int fragmentLength) { |
|
925 |
|
926 byte[] nonce = new byte[0]; |
|
927 switch (cipherType) { |
|
928 case BLOCK_CIPHER: |
|
929 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { |
|
930 // For block ciphers, the explicit IV length is of length |
|
931 // SecurityParameters.record_iv_length, which is equal to |
|
932 // the SecurityParameters.block_size. |
|
933 // |
|
934 // Generate a random number as the explicit IV parameter. |
|
935 nonce = new byte[cipher.getBlockSize()]; |
|
936 random.nextBytes(nonce); |
|
937 } |
|
938 break; |
|
939 case AEAD_CIPHER: |
|
940 // To be unique and aware of overflow-wrap, sequence number |
|
941 // is used as the nonce_explicit of AEAD cipher suites. |
|
942 nonce = authenticator.sequenceNumber(); |
|
943 |
|
944 // initialize the AEAD cipher for the unique IV |
|
945 byte[] iv = Arrays.copyOf(fixedIv, |
|
946 fixedIv.length + nonce.length); |
|
947 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length); |
|
948 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); |
|
949 try { |
|
950 cipher.init(mode, key, spec, random); |
|
951 } catch (InvalidKeyException | |
|
952 InvalidAlgorithmParameterException ikae) { |
|
953 // unlikely to happen |
|
954 throw new RuntimeException( |
|
955 "invalid key or spec in GCM mode", ikae); |
|
956 } |
|
957 |
|
958 // update the additional authentication data |
|
959 byte[] aad = authenticator.acquireAuthenticationBytes( |
|
960 contentType, fragmentLength); |
|
961 cipher.updateAAD(aad); |
|
962 break; |
|
963 } |
|
964 |
|
965 return nonce; |
|
966 } |
|
967 |
|
968 /* |
|
969 * Is this cipher available? |
|
970 * |
|
971 * This method can only be called by CipherSuite.BulkCipher.isAvailable() |
|
972 * to test the availability of a cipher suites. Please DON'T use it in |
|
973 * other places, otherwise, the behavior may be unexpected because we may |
|
974 * initialize AEAD cipher improperly in the method. |
|
975 */ |
|
976 Boolean isAvailable() { |
|
977 // We won't know whether a cipher for a particular key size is |
|
978 // available until the cipher is successfully initialized. |
|
979 // |
|
980 // We do not initialize AEAD cipher in the constructor. Need to |
|
981 // initialize the cipher to ensure that the AEAD mode for a |
|
982 // particular key size is supported. |
|
983 if (cipherType == AEAD_CIPHER) { |
|
984 try { |
|
985 Authenticator authenticator = |
|
986 new Authenticator(protocolVersion); |
|
987 byte[] nonce = authenticator.sequenceNumber(); |
|
988 byte[] iv = Arrays.copyOf(fixedIv, |
|
989 fixedIv.length + nonce.length); |
|
990 System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length); |
|
991 GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv); |
|
992 |
|
993 cipher.init(mode, key, spec, random); |
|
994 } catch (Exception e) { |
|
995 return Boolean.FALSE; |
|
996 } |
|
997 } // Otherwise, we have initialized the cipher in the constructor. |
|
998 |
|
999 return Boolean.TRUE; |
|
1000 } |
710 } |
1001 } |
711 } |