Commits

Stephen Smalley  committed d3a0def Merge

Merge branch 'master' into seandroid

  • Participants
  • Parent commits bcdd08f, a5a2de5
  • Branches seandroid

Comments (0)

Files changed (2)

File core/java/android/net/SSLCertificateSocketFactory.java

     private TrustManager[] mTrustManagers = null;
     private KeyManager[] mKeyManagers = null;
     private byte[] mNpnProtocols = null;
+    private byte[] mAlpnProtocols = null;
     private PrivateKey mChannelIdPrivateKey = null;
 
     private final int mHandshakeTimeoutMillis;
      *     must be non-empty and of length less than 256.
      */
     public void setNpnProtocols(byte[][] npnProtocols) {
-        this.mNpnProtocols = toNpnProtocolsList(npnProtocols);
+        this.mNpnProtocols = toLengthPrefixedList(npnProtocols);
+    }
+
+    /**
+     * Sets the
+     * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">
+     * Application Layer Protocol Negotiation (ALPN)</a> protocols that this peer
+     * is interested in.
+     *
+     * <p>For servers this is the sequence of protocols to advertise as
+     * supported, in order of preference. This list is sent unencrypted to
+     * all clients that support ALPN.
+     *
+     * <p>For clients this is a list of supported protocols to match against the
+     * server's list. If there is no protocol supported by both client and
+     * server then the first protocol in the client's list will be selected.
+     * The order of the client's protocols is otherwise insignificant.
+     *
+     * @param protocols a non-empty list of protocol byte arrays. All arrays
+     *     must be non-empty and of length less than 256.
+     * @hide
+     */
+    public void setAlpnProtocols(byte[][] protocols) {
+        this.mAlpnProtocols = toLengthPrefixedList(protocols);
     }
 
     /**
      * Returns an array containing the concatenation of length-prefixed byte
      * strings.
      */
-    static byte[] toNpnProtocolsList(byte[]... npnProtocols) {
-        if (npnProtocols.length == 0) {
-            throw new IllegalArgumentException("npnProtocols.length == 0");
+    static byte[] toLengthPrefixedList(byte[]... items) {
+        if (items.length == 0) {
+            throw new IllegalArgumentException("items.length == 0");
         }
         int totalLength = 0;
-        for (byte[] s : npnProtocols) {
+        for (byte[] s : items) {
             if (s.length == 0 || s.length > 255) {
                 throw new IllegalArgumentException("s.length == 0 || s.length > 255: " + s.length);
             }
         }
         byte[] result = new byte[totalLength];
         int pos = 0;
-        for (byte[] s : npnProtocols) {
+        for (byte[] s : items) {
             result[pos++] = (byte) s.length;
             for (byte b : s) {
                 result[pos++] = b;
     }
 
     /**
+     * Returns the
+     * <a href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-01">Application
+     * Layer Protocol Negotiation (ALPN)</a> protocol selected by client and server, or null
+     * if no protocol was negotiated.
+     *
+     * @param socket a socket created by this factory.
+     * @throws IllegalArgumentException if the socket was not created by this factory.
+     * @hide
+     */
+    public byte[] getAlpnSelectedProtocol(Socket socket) {
+        return castToOpenSSLSocket(socket).getAlpnSelectedProtocol();
+    }
+
+    /**
      * Sets the {@link KeyManager}s to be used for connections made by this factory.
      */
     public void setKeyManagers(KeyManager[] keyManagers) {
     public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
         s.setNpnProtocols(mNpnProtocols);
+        s.setAlpnProtocols(mAlpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
         s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
     public Socket createSocket() throws IOException {
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
         s.setNpnProtocols(mNpnProtocols);
+        s.setAlpnProtocols(mAlpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
         s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
                 addr, port, localAddr, localPort);
         s.setNpnProtocols(mNpnProtocols);
+        s.setAlpnProtocols(mAlpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
         s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
     public Socket createSocket(InetAddress addr, int port) throws IOException {
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
         s.setNpnProtocols(mNpnProtocols);
+        s.setAlpnProtocols(mAlpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
         s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         return s;
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
                 host, port, localAddr, localPort);
         s.setNpnProtocols(mNpnProtocols);
+        s.setAlpnProtocols(mAlpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
         s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {
     public Socket createSocket(String host, int port) throws IOException {
         OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
         s.setNpnProtocols(mNpnProtocols);
+        s.setAlpnProtocols(mAlpnProtocols);
         s.setHandshakeTimeout(mHandshakeTimeoutMillis);
         s.setChannelIdPrivateKey(mChannelIdPrivateKey);
         if (mSecure) {

File core/tests/coretests/src/android/net/SSLTest.java

         // System.out.println(new String(b));
     }
 
-    public void testStringsToNpnBytes() {
+    public void testStringsToLengthPrefixedBytes() {
         byte[] expected = {
                 6, 's', 'p', 'd', 'y', '/', '2',
                 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
         };
-        assertTrue(Arrays.equals(expected, SSLCertificateSocketFactory.toNpnProtocolsList(
+        assertTrue(Arrays.equals(expected, SSLCertificateSocketFactory.toLengthPrefixedList(
                 new byte[] { 's', 'p', 'd', 'y', '/', '2' },
                 new byte[] { 'h', 't', 't', 'p', '/', '1', '.', '1' })));
     }
 
-    public void testStringsToNpnBytesEmptyArray() {
+    public void testStringsToLengthPrefixedBytesEmptyArray() {
         try {
-            SSLCertificateSocketFactory.toNpnProtocolsList();
+            SSLCertificateSocketFactory.toLengthPrefixedList();
             fail();
         } catch (IllegalArgumentException expected) {
         }
     }
 
-    public void testStringsToNpnBytesEmptyByteArray() {
+    public void testStringsToLengthPrefixedBytesEmptyByteArray() {
         try {
-            SSLCertificateSocketFactory.toNpnProtocolsList(new byte[0]);
+            SSLCertificateSocketFactory.toLengthPrefixedList(new byte[0]);
             fail();
         } catch (IllegalArgumentException expected) {
         }
     }
 
-    public void testStringsToNpnBytesOversizedInput() {
+    public void testStringsToLengthPrefixedBytesOversizedInput() {
         try {
-            SSLCertificateSocketFactory.toNpnProtocolsList(new byte[256]);
+            SSLCertificateSocketFactory.toLengthPrefixedList(new byte[256]);
             fail();
         } catch (IllegalArgumentException expected) {
         }