Uploaded image for project: 'Santuario'
  1. Santuario
  2. SANTUARIO-610

NullPointerException in XMLCipher with BC AES GCM NoPadding

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Critical
    • Resolution: Fixed
    • Java 3.0.1, Java 4.0.2
    • Java 3.0.5, Java 4.0.3
    • Java
    • None

    Description

      I encountered a NullPointerException when using the XMLCipher#encryptData(org.w3c.dom.Document, org.w3c.dom.Element, java.lang.String, java.io.InputStream) method in conjunction with BC AES GCM NoPadding.

      If the input data is not a multiple of the AES block size If the input data is 1-15 bytes larger than the initial buffer of 8192 bytes, the BC implementation returns null. This behavior is consistent with the JDK SPI javax.crypto.Cipher#update(byte[], int, int), which states:

      Returns:
      the new buffer with the result, or null if the underlying cipher is a block cipher and the input data is too short to result in a new block.

      However, this leads to a NullPointerException in XMLCipher.

      Steps to Reproduce

      1. Provide a byte array which is not a multiple of AES block size Provide a byte array which is 1-15 bytes larger than the buffer of 8192 bytes
      2. Initialize XMLCipher
      3. Try to encrypt data

      Code snippet

      Security.insertProviderAt(new BouncyCastleProvider(), 1);
      
      KeyGenerator generator = KeyGenerator.getInstance("AES", BouncyCastleProvider.PROVIDER_NAME);
      generator.init(128);
      SecretKey sessionKey = generator.generateKey();
      
      XMLCipher xmlCipher = XMLCipher.getInstance(XMLCipher.AES_128_GCM);
      xmlCipher.init(XMLCipher.ENCRYPT_MODE, sessionKey);
      
      SOAPMessage soapMsg = loadSoapMsg();
      Document soapDoc = soapMsg.getSOAPPart().getOwnerDocument();
      EncryptedData data = xmlCipher.encryptData(soapDoc, null, new ByteArrayInputStream(dataToEncrypt));

      Expected Result:

      The encrypted cipher text

      Actual Result

      NullPointerException

      Hints

      I debugged the code and found a potential issue here

      try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
          while ((numBytes = serializedData.read(buf)) != -1) {
              byte[] data = c.update(buf, 0, numBytes);
              baos.write(data);
          }
          baos.write(c.doFinal());
          encryptedBytes = baos.toByteArray();
      }
      

      I assume that one only needs to wrap baos.write(data) in an if statement and doFinal encrypts the remaining bytes:

      if (data != null) {
          baos.write(data);
      }
      

      Attachments

        Issue Links

          Activity

            People

              coheigea Colm O hEigeartaigh
              bkrahl-asd Benjamin Krahl
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: