src/java.base/share/classes/javax/crypto/CipherSpi.java
changeset 55661 b32b6ffb221b
parent 50510 e93ba293e962
equal deleted inserted replaced
55660:fe5dcb38a26a 55661:b32b6ffb221b
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
   759         if (output.remaining() < outLenNeeded) {
   759         if (output.remaining() < outLenNeeded) {
   760             throw new ShortBufferException("Need at least " + outLenNeeded
   760             throw new ShortBufferException("Need at least " + outLenNeeded
   761                 + " bytes of space in output buffer");
   761                 + " bytes of space in output buffer");
   762         }
   762         }
   763 
   763 
       
   764         // detecting input and output buffer overlap may be tricky
       
   765         // we can only write directly into output buffer when we
       
   766         // are 100% sure it's safe to do so
       
   767 
   764         boolean a1 = input.hasArray();
   768         boolean a1 = input.hasArray();
   765         boolean a2 = output.hasArray();
   769         boolean a2 = output.hasArray();
   766         int total = 0;
   770         int total = 0;
   767         byte[] inArray, outArray;
   771 
   768         if (a2) { // output has an accessible byte[]
   772         if (a1) { // input has an accessible byte[]
   769             outArray = output.array();
   773             byte[] inArray = input.array();
   770             int outPos = output.position();
   774             int inOfs = input.arrayOffset() + inPos;
   771             int outOfs = output.arrayOffset() + outPos;
   775 
   772 
   776             if (a2) { // output has an accessible byte[]
   773             if (a1) { // input also has an accessible byte[]
   777                 byte[] outArray = output.array();
   774                 inArray = input.array();
   778                 int outPos = output.position();
   775                 int inOfs = input.arrayOffset() + inPos;
   779                 int outOfs = output.arrayOffset() + outPos;
       
   780 
       
   781                 // check array address and offsets and use temp output buffer
       
   782                 // if output offset is larger than input offset and
       
   783                 // falls within the range of input data
       
   784                 boolean useTempOut = false;
       
   785                 if (inArray == outArray &&
       
   786                     ((inOfs < outOfs) && (outOfs < inOfs + inLen))) {
       
   787                     useTempOut = true;
       
   788                     outArray = new byte[outLenNeeded];
       
   789                     outOfs = 0;
       
   790                 }
   776                 if (isUpdate) {
   791                 if (isUpdate) {
   777                     total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
   792                     total = engineUpdate(inArray, inOfs, inLen, outArray, outOfs);
   778                 } else {
   793                 } else {
   779                     total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
   794                     total = engineDoFinal(inArray, inOfs, inLen, outArray, outOfs);
   780                 }
   795                 }
       
   796                 if (useTempOut) {
       
   797                     output.put(outArray, outOfs, total);
       
   798                 } else {
       
   799                     // adjust output position manually
       
   800                     output.position(outPos + total);
       
   801                 }
       
   802                 // adjust input position manually
   781                 input.position(inLimit);
   803                 input.position(inLimit);
   782             } else { // input does not have accessible byte[]
   804             } else { // output does not have an accessible byte[]
   783                 inArray = new byte[getTempArraySize(inLen)];
   805                 byte[] outArray = null;
   784                 do {
       
   785                     int chunk = Math.min(inLen, inArray.length);
       
   786                     if (chunk > 0) {
       
   787                         input.get(inArray, 0, chunk);
       
   788                     }
       
   789                     int n;
       
   790                     if (isUpdate || (inLen > chunk)) {
       
   791                         n = engineUpdate(inArray, 0, chunk, outArray, outOfs);
       
   792                     } else {
       
   793                         n = engineDoFinal(inArray, 0, chunk, outArray, outOfs);
       
   794                     }
       
   795                     total += n;
       
   796                     outOfs += n;
       
   797                     inLen -= chunk;
       
   798                 } while (inLen > 0);
       
   799             }
       
   800             output.position(outPos + total);
       
   801         } else { // output does not have an accessible byte[]
       
   802             if (a1) { // but input has an accessible byte[]
       
   803                 inArray = input.array();
       
   804                 int inOfs = input.arrayOffset() + inPos;
       
   805                 if (isUpdate) {
   806                 if (isUpdate) {
   806                     outArray = engineUpdate(inArray, inOfs, inLen);
   807                     outArray = engineUpdate(inArray, inOfs, inLen);
   807                 } else {
   808                 } else {
   808                     outArray = engineDoFinal(inArray, inOfs, inLen);
   809                     outArray = engineDoFinal(inArray, inOfs, inLen);
   809                 }
   810                 }
   810                 input.position(inLimit);
       
   811                 if (outArray != null && outArray.length != 0) {
   811                 if (outArray != null && outArray.length != 0) {
   812                     output.put(outArray);
   812                     output.put(outArray);
   813                     total = outArray.length;
   813                     total = outArray.length;
   814                 }
   814                 }
   815             } else { // input also does not have an accessible byte[]
   815                 // adjust input position manually
   816                 inArray = new byte[getTempArraySize(inLen)];
   816                 input.position(inLimit);
   817                 do {
   817             }
   818                     int chunk = Math.min(inLen, inArray.length);
   818         } else { // input does not have an accessible byte[]
   819                     if (chunk > 0) {
   819             // have to assume the worst, since we have no way of determine
   820                         input.get(inArray, 0, chunk);
   820             // if input and output overlaps or not
   821                     }
   821             byte[] tempOut = new byte[outLenNeeded];
   822                     int n;
   822             int outOfs = 0;
   823                     if (isUpdate || (inLen > chunk)) {
   823 
   824                         outArray = engineUpdate(inArray, 0, chunk);
   824             byte[] tempIn = new byte[getTempArraySize(inLen)];
   825                     } else {
   825             do {
   826                         outArray = engineDoFinal(inArray, 0, chunk);
   826                 int chunk = Math.min(inLen, tempIn.length);
   827                     }
   827                 if (chunk > 0) {
   828                     if (outArray != null && outArray.length != 0) {
   828                     input.get(tempIn, 0, chunk);
   829                         output.put(outArray);
   829                 }
   830                         total += outArray.length;
   830                 int n;
   831                     }
   831                 if (isUpdate || (inLen > chunk)) {
   832                     inLen -= chunk;
   832                     n = engineUpdate(tempIn, 0, chunk, tempOut, outOfs);
   833                 } while (inLen > 0);
   833                 } else {
       
   834                     n = engineDoFinal(tempIn, 0, chunk, tempOut, outOfs);
       
   835                 }
       
   836                 outOfs += n;
       
   837                 total += n;
       
   838                 inLen -= chunk;
       
   839             } while (inLen > 0);
       
   840             if (total > 0) {
       
   841                 output.put(tempOut, 0, total);
   834             }
   842             }
   835         }
   843         }
       
   844 
   836         return total;
   845         return total;
   837     }
   846     }
   838 
   847 
   839     /**
   848     /**
   840      * Wrap a key.
   849      * Wrap a key.