Getting z/OS Explorer to work with z/OS Connect EE

Ive been trying to set up z/OS Connect, so I could look at the MQ support within it.

Setting up z/OS Connect in the first place, was a challenge, which I’ll blog about some other time.  I was looking for an Installation Verification Program (IVP) and tried to use the z/OS Explorer.  This was another challenge.  Like many problem there are answers, but it is hard to find the information.

Installing z/OS Explorer

This was easy.  I started here and installed z/OS explorer for Aqua – Eclipse tools.  Then select  IBM z/OS Connect EE.  I selected Aqua 3.2, and chose to install using eclipse p2. I have tried to avoid installation manager as it always seemed very complex and frustrating.

I tried to extend an existing eclipse, but this failed due to incompatibilities.  I used start from fresh, and this worked fine.

Adjust the z/OS Connect server configuration.

I enabled logon logging.

 <httpEndpoint id="defaultHttpEndpoint" 
    host="*" 
    accessLoggingRef="hal1" 
    httpPort="19080" 
    httpsPort="19443" > 
   <accessLogging enabled="true" 
     logFormat='h:%h i:%i u:%u t:%t r:%r s:%s b:%b D: %D m:%m' 
    /> 
<sslOptions sslRef="defaultSSLSettings"/> 
</httpEndpoint> 

This creates a file in the  location http_access.log within the log directory. It has output like

10.1.1.1 ADCDC 08/Sep/2020:17:50:40 +0000 "GET /zosConnect/services/stockQuery HTTP/1.1" 200

You can see where the request came from (10.1.1.1), user (ADCDC), the date and time, the request (“GET /zosConnect/services/stockQuery HTTP/1.1”), and the response code(200).

Getting started with z/OS Explorer

You need to define host connections.

If you totally disable security on your server you can use http.

  1. On z/OS explorer,display the Connections tab. (Window -> Show View -> Host connections)
  2. Right click on z/OS Connect Enterprise Edition, and select New z/OS Connect Enterprise Edition, Connection
    1. Name: this is displayed in the tooling
    2. Host name: I used 10.1.3.10 which is my VIPA address of the server
    3. Port number:   This comes from the  httpEndpoint for the server.  The default is http:9080 and https:9443 – but as every Liberty product uses these values, your server may have different values.  I used 19080.
    4. I initially left Secure connection(TLS/SSL) unticked
    5. Click Save and Connect
  3. A panel was displayed asking for credentials. Either create new credentials (userid and password) or select an existing credential.
  4. Double click on the connection you just created.
    1. An error of “302, Found” is an http response meaning redirection.  In the z/OS connect case, this means you are trying to use an http connection when an https ( a TLS connection) was expected.  I got this because I had not disabled security in my server.

The normal way of accessing z/OS connect is to use TLS to protect the session.  As well as TLS to protect the session you can also use client certificate authentication.  This is what I used.

You will need to set up certificates, keystores and keyrings on z/OS and get the Certificate Authority certificates sent to the “other” system.  I used my definitions from using MQWEB.

  1. On z/OS explorer, set up the keystores
    1. Window -> Preferences -> Explorer-> certificate manager
    2. The truststore contains the CA certificates to validate the certificate send down from the z/OS server.  Enter the file name (or use Browse), the pass phrase, and the key store.  My truststore was JKS.
    3. The keystore contains the client certificate used to identify this client to the server.
    4. Smart card details.  Ignore this – (despite it saying you must configure a PKCS11 driver).   This section is used if you select smart card to identify yourself, and it would be better if the wording said “If you are using Smart card authentication you must configure a PKCS11 driver ).
    5. Leave the “Do not validate server certificate trust” unticked.  This will check the passwords etc of the key stores.
    6. At the bottom I used “Secure socket protocol-> TLS v1.2” though this is optional.
    7. Select Apply and Close
  2. Display the Connections tab. (Window -> Show View -> Host connections)
  3. Right click on z/OS Connect Enterprise Edition, and select New z/OS Connect Enterprise Edition, Connection
    1. Name: this is displayed in the tooling
    2. Host name: I used 10.1.3.10 which is my VIPA address of the server
    3. Port number:   This comes from the  httpEndpoint for the server.  The default is http:9080 and https:9443 – but as every Liberty product uses these values, your server may have different values.  I used 19443
    4. I ticked Secure connection(TLS/SSL).  If you do not select this, you will not be able to use a certificate to logon.
    5. Click Save and Connect
  4. A panel was displayed asking for credentials.   When I used an existing credential I failed to connect to the server.
    1. Select Create new credentials
    2. Click on Username and Password pull down – and select Certificate from Keystore.
    3. Enter credentials name – this is just used within the tooling
    4. Userid – this seems to be ignored.  I used certificate mapping on the z/OS to map the certificate to a userid.
    5. Choose a certificate – select one from the pull down.  In my Linux box the choice of certificates came out in yellow writing on a yellow background!
    6. Click OK
    7. The connection should appear on the Connections page, under z/OS Connect Enterprise Edition.  It should go yellow while it is connecting, and green, with a padlock once it has connected

Use z/OS Connect

Use Window-> Show View -> zOS Connect EE Servers

You should see your connection displayed  with the IP address and port. Underneath this are any APIs or Services you have defined.

If you have any APIs or Services, you should be able to right click and select Show Properties View.  You can click on the links, or copy the links and use them, for example  in a web browser directly,or via curl.

If you try to use the APIs or Services, you may not be authorised.  You will need to configure

  1. <zosconnect_zosConnectManager …>
  2. <zosconnect_zosConnectAPIs>   <zosConnectAPI name=”stockmanager”  ….
  3. <zosconnect_service>  <service name=”stockquery”

Good luck.

 

 

 

Liberty on z/OS: Mapping an incoming certificate to a z/OS userid for client certificate authentication – and don’t forget the cookies!

I thought I understood how this worked, I found I didn’t, then had a few days hunting around for the problem

The basics

You can use a digital certificate from a web browser ( curl, or other tools) to authenticate to z/OS.  You need to map the certificate to a userid.

A certificate coming in can have a Distinguished Name like CN=adcdd.O=cpwebuser.C=GB  (Note the ‘.’not ‘,’ between elements).

Your userid needs to have SPECIAL define to be able to use the RACDCERT command (SPECIAL, not just GROUP-SPECIAL).

You will need a definition like (see here for the command)

RACDCERT MAP ID(ADCDD ) - 
    SDNFILTER('CN=adcdd.O=cpwebuser.C=GB') - 
    WITHLABEL('adcdd')

or a general definition for those certificate with  O=cpwebuser.C=GB, ignoring the CN part

RACDCERT MAP ID(ADCDB ) - 
   SDNFILTER('O=cpwebuser.C=GB') - 
   WITHLABEL('cpwerbusergb') 

or using the Issuing Distinguished Name (the Certificate Authority)

IDNFILTER(‘CN=TESTCA.OU=SSSCA.C=GB)

Using a generic

SDNFILTER(‘CN=a*.O=cpwebuser.C=GB’)

does not work.

If you attempt to use a certificate which is not mapped you get

ICH408I USER(START1 ) GROUP(SYS1 ) NAME(COLIN)
DIGITAL CERTIFICATE IS NOT DEFINED. CERTIFICATE SERIAL NUMBER(0163)  SUBJECT(CN=adcdd.O=cpwebuser.C=GB) ISSUER(CN=SSCA8.OU=CA.O=SSS.C=GB).

It is worth defining these using JCL, because if you try to add it, and it already exists then you get a message saying it exists already.  If you know the userid, you can list the maps associated with it.   If you do not know the userid, there is no practical way of finding out – you have to logon with the certificate, and display the userid from the web browser, or extract the list of all users, and use LISTMAP on all of them.

Once you have set up the userid, you can connect them to the group to give them access to the EJBROLE profiles.  For example use group names

  • MQPAWCO MQPAMQWebAdminRO Console Read Only.
  • MQPAWCU MQPAMQWebUser  Console User only.  The request operates under the signed on userid authority.
  • MQPAWCA MQPAMQWebAdmin Console Admin.

for queue manager MQPA, Web  Console (rather than REST) and the access.

You may want to set up  userids solely for client authentication.  If the userid has NOPASSWORD, it cannot be used to logon with userid and password, and of course the lack of password means the password will not expire.

Having a set of userids just for certificate access makes it easier to manage the RACDCERT MAPping.    You have a job with

RACDCERT ID(adcd1) LISTMAP
RACDCERT ID(adcd2) LISTMAP
etc

and search the output for the certificate of interest.

It gets more complicated…

Often the user’s certificate is in the form CN=Colin Paice,o=SSS,C=GB so if you want to allow all people in the MQADMIN team access, you will need to to specify them individually.  It would be easier if DN had CN=Colin Paice,OU=MQADMIN,o=SSS,C=GB, then you can filter on the OU=MQADMIN.   These could map to a userid MQADM1.

It gets more complication if someone can work with MQ, and CICS or z/OS Connect, and you have to decide a userid – MQADM1 or CICSADM1?

Setting up a one to one mapping may be the best solution, so CN=Colin Paice,o=SSS,C=GB maps to CPAICE (or GB070594).   This userid is then added to the appropriate RACF groups to give access to the EJBROLEs, to give access to the servers.

How do I tell what is being used?

I could not get Liberty to record an audit record for the logon/matching.   I tried altering the userid to have UADIT – but it did not work either.

If you have audit defined on the class EJBROLE profile MQWEB.com.ibm.mq.console.MQWebUser, you will get a audit record in SMF.   This has many fields including

  • Date
  • Time
  • ACCESS
  • SUCCESS – or INSACC (INSufficient Access)
  • ADCDC – userid being used
  • READ – Requested access
  • READ – permitted access
  • EJBROLE – the class
  • MQWEB.com.ibm.mq.console.MQWebUser – the profile
  • CN=adcdd.O=cpwebuser.C=GB – the Distinguished Name of the certificate
  • CN=SSCA8.OU=CA.O=SSS.C=GB – the Issuers (Certificate Authority) of the certificate

From this you can see the userid being used ACDC, and the certificate DN CN=adcdd.O=cpwebuser.C=GB.

And to make it more complicated

I deleted the RACDCERT MAP entry, but the web browser continued to work with the user.  I had a cup of tea and a cookie, and the web browser stopped working.   Was problem this connected to a cup of tea and a cookie?

Setting up the initial handshake is expensive.  The system has to do a logon with the certificate to get the userid from the RACDCERT mapping.  It then checks the userid has access to the SERVER profile, then it checks to see if it is MQWebAdmin, MQWebAdminRO, or  MQWebUser.

Once it has done this it it takes the userid and information, encrypts it, and creates the LTPA cookie.   This is sent down to the web browser.

The next time the web browser sends some data, it also sends the cookie. The MQWEB server decrypts the cookie, checks the time stamp to make sure the information is current, and if so, uses it.  The timeline I had was

  • create the RACDCERT mapping from certificate DN to userid
  • use browser to logon to mqweb, using the certificate with the DN
  • it works, mqweb sends down the cooke
  • delete the RACDCERT mapping for the DN
  • restart the browser, logon to mqweb, using the certificate with the DN.  The cookie is passed up – the logon works
  • clear the browser’s cookies – and retry the logon.  It fails as expected.

So ensure the browser cookie is cleared if you change the mapping or ejbrole access for the user.

Playing twister with Liberty and falling over

Twister is a game where you have you put your left foot here, your left hand there, your right foot here, and in trying to put your right hand over there you fall over.  This is how I felt when I was trying to understand the SSL definitions in MQWEB.  In the end I printed off the definitions and used coloured pens to mark the relevant data.

Let’s start with the easy bit.

  • When mqweb starts, it reads configuration information from a file server.xml
  • This includes two files the “IBM” stuff in  /usr/lpp/mqm/V9R1M1/web/mq/etc/mqweb.xml and the user stuff in /u/mqweb/servers/mqweb/mqwebusr.xml .
  • SSL parameters are defined with and <ssl… id=”thisSSLConfig”   keyStoreRef=”defaultKeyStore” .. /> tag.    This points to the keystore to use.
  • The keystore has <keyStore id=”defaultKeyStore”  ….>.   There is a simple link from SSL to the keystore.   You could have multiple keystores,  if so you just change the  keyStoreRef= to point to a different one.
  • You can have more than one <ssl…/> definition.  You might have one, and there is one in the “IBM stuff”, so you need <sslDefault sslRef=”thisSSLConfig”/>  to point to the ssl statement to use.

That should all be clear, and make sense.   A bit like saying you have a right foot, a left foot and two hands.

The zos_saf_registry.xml used when you want to use the SAF interface on z/OS has some SSL definitions.  I was trying to understand them.   This one here(put a finger on it) points to that one, (put a finger on it), which points to this other one (put a finger on it), which has an end-comment.  Whoops that didn’t work.    As I said a bit like playing Twister.

<sslDefault sslRef=”mqDefaultSSLConfig”/> in the user mqwebuser.xml  points to content in the “IBM stuff”.  By the various levels of indirection this points to <keyStore id=”defaultKeyStore” location=”key.jks” type=”JKS” password=”password”/> .  This keystore has a self signed certificate provided by IBM. If you find your browser complains about using a self signed certificate, this may well be the cause.

In the zos_saf_registry.xml are commented statements

  • <keyStore id=”defaultKeyStore” location=”safkeyring://userId/keyring” …/>
  • <ssl id=”thisSSLConfig”  keyStoreRef=”defaultKeyStore” …/>
  • <sslDefault sslRef=”thisSSLConfig”/>

To me these have been defined upside down, sslDefault should come first.

As these are after the sslDefault sslRef=”mqDefaultSSLConfig statment, if you uncomment them, they will be picked up and the “IBM stuff” will not be processed.

You can uncomment these statements and use them to add your definitions.

My definitions are

<sslDefault sslRef="defaultSSLConfig"/> 
<ssl id="defaultSSLConfig" keyStoreRef="racfKeyStore" 
   sslProtocol="TLSv1.2" 
   clientAuthenticationSupported="true" 
   clientAuthentication="true" 
   serverKeyAlias="LABELMQWEBHSCEKE"/> 

<keyStore filebased="false" id="racfKeyStore" 
   location="safkeyring://START1/MQRING" 
   password="password" 
   readOnly="true" 
   type="JCERACFKS"/> 

<webAppSecurity allowFailOverToBasicAuth="false"/>

Why cant I logoff from mqconsole?

If you are using mqweb using certificates to identify yourself, if you logoff, or close the tab, then open a new tab, you will get a session using the same certificate as before.

This little problem has been a tough one to investigate, and turns out to be lack of function in Chromium browser.

The scenario is you connect to mqweb using a digital certificate. You want to logoff and logon again with a different certificate, for example you do most of your work with a read only userid, and want to logon with a more powerful id to make a change.  You click logoff, and your screen flashes and logs you on again with the same userid as before.

At first glance this may look like a security hole, but if someone has access to your web browser, then the can click on the mqweb site, and just pick a certificate – so it is no different.

Under the covers,  the TLS handshake can pass up the previous session ID.   If the server  recognises this, then it is a short handshake instead of a full hand shake, so helping performance.

To reset the certificate if you are using Firefox

To clear your SSL session state in Firefox choose History -> Clear Recent History… and then select “Active Logins” and click “OK”. Then the next time you connect to your SSL server Firefox will prompt for which certificate to use, you may need to reset the URL.

You should check Firefox preferences, certificates, “Ask you every time” is selected, rather than “Select one automatically”.

Chrome does not support this reset of the certificate.

There has been discussion over the last 9 years along the lines of, seeing as Internet Explorer, and Firefox have there, should we do it to met the end user demand?

If you set up an additional browser instance, you get the same problem. With Chrome you have to close down all instances of the browser and restart chrome to be able to select a different certificate.

It looks like there is code which has a cache of url, and certificate to use.   If you open up another tab using the same IP address you will reuse the same certificate.

If you localhost instead of 127.0.0.1 – it will prompt for certificate, and then cache it, so you can have one tab open with one certificate, and another tab, with a different URL and another certificate.

What is in a cipher suite name? or how to tell your RSA from your ephemeral

Why do we need stronger encryption?

  • To make keys more resilient to attack you need longer keys.
  • There are newer ways of providing better private keys than just using large prime numbers.   For example using the equation y**2= a* x**3 + b * x**2  + c*x + d.  Which you may recognize as a cubic equation, but comes under the name of Elliptic Curves(EC).  (For some values of a,b,c,d if you plot the curve it is an ellipse.)  These Elliptic Curves with small keys are harder to crack than RSA with longer.  They also use less resources during encryption and decryption.
  • Originally public/private certificates were used for both authentication and encryption.  This has the disadvantage that if I monitor your traffic for a year, then steal your private key (for example from the corporate backups) then I can decrypt all of your traffic.  You need to use a technique called Forward Secrecy to prevent this.   This gives assurances that session keys will not be compromised even if the private key of the server is compromised.   With Forward Secrecy
    • You use the public/private key for authentication, and generate a secret for the encryption.   A technique called Diffie-Hellman(DH) can be used to agree an agreed  common secret without a man-in-the middle being able to determine the secret key.   See Wikipedia  for a good description.   This is good – but repeated conversations may use the same common secret and over repeated use, people may be able to guess your key.
    • This problem is fixed by using Ephemeral(E) keys, known as one-time keys, which are valid for just one conversation.  A second conversation will get a different secret key.

You need to support and use ECDHE (Elliptic Curves – Diffie-Hellman – Ephemeral)  suites in order to enable forward secrecy (having the private key means you cannot decrypt the message) with modern web browsers.  Avoid the RSA key exchange unless absolutely necessary.

What does a cipher spec tell us?

This is a good web site which tells you what the cipher spec means.

A cipher spec describes the techniques to be used for authentication, encryption and hashing the data.  This is negotiated between the two ends when setting up a TLS handshake.  The conversation is like “Client: I support the following cipher specs; Server: I like this one…”,  or “Client: I support the following cipher specs; Server: hmm none match”

If you look at the names of cipher suites available with TLS v1.2 you find names like

  • TLS_RSA_WITH_…  this is for a key with public certificate generated with RSA
  • TLS_ECDH_RSA_WITH… this is for a key with public certificate generated with Elliptic Curve(EC) and uses Diffie-Hellman(DH)
  • TLS_ECDHE_ECDSA_WITH…  this is for a key with public certificate generated with Elliptic Curve(EC) and uses Diffie-Hellman(DH) and Ephemeral key (E)

I found this document which is a good introduction to cipher specs TLS 1.2, TLS 1.3 etc

A cipher spec which I use a lot is TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384

Let me break that down into the components

  • TLS indicates the protocol ( old versions might have SSL)
  • ECDHE : Key Exchange Algorithm.  What is used to generate a secret number. Think of a telephone conversation between the UK and China. “Should we talk in English or Chinese”.  “I prefer English”. “OK my information is …”.   In this example  we have  ECDHE:  Elliptic Curve, Diffie-Hellman, Ephemeral.   This can be
    • ECDHE
    • ECDH
    • RSA
    • DH
  • ECDSA:  Authentication/Digital Signature Algorithm: What sort of certificate can be used.
    • ECDSA the server public key is an Elliptic Curvesignifies.  ECDSA is Elliptic Curve + Digital Signing Algorithm.   The TLS spec says it should be signed using a CA with EC public certificate – but it works even if it is signed with an RSA certificate
    • RSA the server public key is created with RSA public certificate.  The TLS spec says it should be signed using a CA with EC public certificate – but it works even if it is signed with an ECDSA certificate
  • “WITH” splits the authentication and encryption from the encryption of the data itself.
  • AES_256_CBC indicates the bulk encryption algorithm: Once the handshake has completed, the encryption of the payload is done using symmetric encryption.  They keys are determined during the handshake.    AES_256 is a symmetric encryption with a 256 bit key using Cipher Block Chaining. (CBC is like using a “running total” of the data encrypted so far, as an input to the encryption).   TLSv1.3 drops support for CBC;  GCM can be used instead. It is faster and can exploit pipeline processors.
  • SHA384 indicates the algorithm for hashing the message (MAC =  Message Authentication Code)

Notes:

  • DSS is a different authentication algorithm. For example TLS_DHE_DSS…   It also stands for Digital for Digital Signature Standard which covers all algorithms – so a touch confusing.
  • Because RSA tends to be used for authentication and encryption, I think of TLS_RSA_WITH… as TLS_RSA_RSA_WITH.   So the secret number generation algorithm is RSA, and then the certificate with an RSA public key is used.

For TLS 1.3 the cipher specs are like  TLS_AES_256_GCM_SHA384 because the key exchange algorithm will be either ECDHE or RSA.

How to restrict what certificates and algorithms clients can use to connect to java web servers

As part of your regular housekeeping you want to limit connections to your web server from weak keys and algorithms.   Making changes to the TLS configuration could be dangerous, as there is no “warning mode” or statistics to tell you if weak algorithms etc are being used.  You have to make a change and be prepared to have problems.

In this posting I’ll explain how to do it, then explain some of the details behind it.

How to restrict what certificates and algorithms can be used by web servers and java programs doing TLS.

One way which does not work.

The jvm.options file provided by mqweb includes commented out

-Djdk.tls.disabledAlgorithms=… and  -Djdk.tls.disabledAlgorithms=…..

These is the wrong way of specifying information, as you do it via the java.security file, not -D… .

Create an mqweb specific private disabled algorithm file

Java uses a java.security file to define security properties.

On my Ubuntu, this file if in /usr/lib/jvm/…/jre/lib/security/java.security  .

Create a file mqweb.java.security.  It can go anywhere – you pass the name using a java system property.

Copy  from the java.security file to your file, the lines with  with jdk.tls.disabledAlgorithms=..  and jdk.certpath.disabledAlgorithms=… . 

On my system, the lines are (but your security people may have changed them – if so,  you might want to talk to them before making any changes)

jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,     EC keySize < 224, 3DES_EDE_CBC, anon, NULL

jdk.certpath.disabledAlgorithms=jdk.certpath.disabledAlgorithms=MD2, MD5,    SHA1 jdkCA & usage TLSServer,    RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224

The jvm.options file provided by IBM has

-Djdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, MD5withRSA, DH keySize < 768, 3DES_EDE_CBC, DESede, EC keySize < 224, SHA1 jdkCA & usage TLSServer

So you may want to add this as in your override file ( without the -D), so add “, SHA1 jdkCA & usage TLSServer” to  jdk.certpath.disabledAlgorithms .

Tell mqweb to use this file

Create a java system property in the mqweb jvm.options file

“-Djava.security.properties=/home/colinpaice/eclipse-workspace-C/sslJava/bin/serverdisabled.properties”

Restart your web server.  You have not changed anything – just copied some definitions into an mqweb specific file, so it should work as before.

Limit what can be used

I set up several certificates with combination of RSA and Elliptic Curves, varying keysize, signatures;  and signed with CAs with RSA, and Elliptic Curve, and different signatures.

For example RSA4096,SHA256withECDSA,/EC256,SHA384with ECDSA means

  • RSA4096 certificate is RSA with a key size of 4096
  • SHA256withECDSA signed with this
  • /EC256 the CA has a public key of EC 256
  • SHA384with ECDSA and the CA was signed with this

I then specified different options in the servers’ file, and recorded if they TLS connection worked or not; if not – why not.

certpath: RSA keySize <= 2048

Server EC407,   SHA256withRSA,   /RSA4096,   SHA512withRSA

  • ✅RSA4096,SHA256withECDSA,   /EC256,SW=SHA384with ECDSA
  • RSA2048, SHA256withRSA,      /RSA4096,/SHA512withRSA
  • ✅ EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA
  • ✅EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

certpath: RSA keySize <= 4096

Server EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA

  • RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA
  • RSA2048,SHA256withRSA,     /RSA4096,  SHA512withRSA
  • ❌EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA
  • ✅EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

certpath:EC keySize <= 256

Server EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA

  • ❌  RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA
  • ✅ RSA2048,SHA256withRSA,       /RSA4096,  SHA512withRSA
  • ✅ EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA
  • ❌ EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

tls:EC keySize <= 256

Server EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA

  • ✅ RSA4096,SHA256withECDSA,   /EC256,       SHA384with ECDSA
  • ✅ RSA2048,SHA256withRSA,        /RSA4096,  SHA512withRSA
  • ✅ EC407,      SHA256withRSA,       /RSA4096, SHA512withRSA
  • ✅ EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

certpath: SHA256withRSA

Server EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA

  • ✅ RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA
  • ❌RSA2048,SHA256withRSA,     /RSA4096,  SHA512withRSA
  • ❌ EC407,      SHA256withRSA,    /RSA4096, SHA512withRSA
  • ✅ EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

tls:SHA256withRSA

Server EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA

  • ✅ RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA
  • ❌RSA2048,SHA256withRSA,     /RSA4096,  SHA512withRSA
  • ❌ EC407,      SHA256withRSA,    /RSA4096, SHA512withRSA
  • ✅ EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

either: RSA

Server RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA

All requests failed due to the server’s RSA.   Only 18 out of 50 cipher suites were available.  Server reported javax.net.ssl.SSLHandshakeException: no cipher suites in common

  • ❌RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA
  • ❌ RSA2048,SHA256withRSA,     /RSA4096,  SHA512withRSA
  • ❌ EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA
  • ❌EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

certpath: RSA keySize == 4096

Server RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA

This was a surprise as I did not think this would work!

  • RSA4096,SHA256withECDSA, /EC256,       SHA384with ECDSA
  • RSA2048,SHA256withRSA,     /RSA4096,  SHA512withRSA
  • ❌EC407,      SHA256withRSA,      /RSA4096, SHA512withRSA
  • ✅EC384,       SHA256withECDSA, /EC256,      SHA384withECDSA

Summary of overriding.

You can specify restrictions in the server’s jdk.certpath.disabledAlgorithms and jdk.certpath.disabledAlgorithms. The restrictions apply to the how the certificate has been signed and the CA certificate.

You should check that the server’s certificate is not affected.

More details and what happens under the covers

The section below may be too much information, unless you are trying to work out why something is not working.

In theory jdk.tls.disabledAlgorithms and jdk.certpath.disabledAlgorithms are used for different areas of checking – reading certificates from key files, and what is passed during the handshake – but this does not seem to be true.  I found that it was best to put restrictions on both lines.

A certificate is of type RSA, EC, or DSA.

A certificate is signed for example Signature Algorithm: SHA256withECDSA.   This comes from the CA which signed it, message digest SHA256, and the CA is an Elliptic Curve.  See How do I create a certificate with Elliptic Curve (or RSA).

Signature Algorithms: is a combination of Hash Algorithm and Signature Type.   There are 6 hash algorithms: md5, sha1, sha224, sha256, sha384, sha512, and three types:  rsa, dsa, ecdsa.    These can be combined to to give 14 combinations of Signature Algorithms used in TLSv1.2

You can use java.security to control what TLS does.  On my Ubuntu this file /usr/lib/jvm/java-8-oracle/jre/lib/security/java.security.

This includes

  • jdk.certpath.disabledAlgorithms: Algorithm restrictions for certification path (CertPath) processing:  In some environments, certain algorithms or key lengths may be undesirable for certification path building and validation. For example, “MD2” is generally no longer considered to be a secure hash algorithm. This section describes the mechanism for disabling algorithms based on algorithm name
    and/or key length. This includes algorithms used in certificates, as well as revocation information such as CRLs and signed OCSP Responses.
  • jdk.tls.disabledAlgorithms: Algorithm restrictions for Secure Socket Layer/Transport Layer Security  (SSL/TLS) processing.  In some environments, certain algorithms or key lengths may be undesirable when using SSL/TLS. This section describes the mechanism for disabling algorithms during SSL/TLS security parameters negotiation, including protocol version negotiation, cipher suites selection, peer authentication and key exchange mechanisms.

I found you get better diagnostics if you put the restrictions on both statements.

The TLS Handshake (relating to java.security)

Server starts  up

  • I had 50 available cipher suites
  • Using -Djdk.tls.server.cipherSuites=…,… you can specify a comma separated list of  which cipher suites you want make available.  I recommend you do not specify this and use the defaults.
  • Using jdk.tls.disabledAlgorithm you can specify which handshake information is not allowed.  For example
    •  Any of the following would stop cipher suite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 from being used
      • java.security.tls = AES_256_CBC
      • java.security.tls= SHA384 – this loses 4 certificate TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 etc
      • java.security.tls=TLS_ECDHE_ECDSA
    • Elliptic curves names Extension elliptic_curves, curve names: {secp256r1, secp384r1, secp521r1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, secp256k1}.  Specifying EC keySize <= 521 would only allow {sect571k1, sect571r1} to be used
  • The server builds a supported list of cipher suites, signature algorithm, and elliptic curve names

Client starts up

  • As with the server, the client builds up a list of supported cipher suites, signature algorithms, and supported Elliptic curve names.
  • The client sends “ClientHello” and the list to the server.

Server processes

  • The server takes this list and iterates over it  to find the first acceptable certificate ( or for wlp, if <ssl … serverKeyAlias=”…” />, then the specified aliases  is used )
    • if the cipher suite name is like  TLS_AAA_BBB_WITH…   BBB must match the servers certificate type ( RSA, Elliptic Curve, DSA)
    • the signature algorithm.   This is the algorithm for encrypting the payload, and the algorithm for calculating the hash of the payload
    • if the certificate is EC,  check the  elliptic curve name is valid.  A  server’s certificate created with openssl ecparam -name prime256v1, would be blocked if EC keySize <= 256 was specified in the client resulting.
  • If no certificate was found in the trust store which passed all of the checks, it throws javax.net.ssl.SSLHandshakeException: no cipher suites in common , and closes the connection
  • The server sends “ServerHello” and the server’s public key to the client.
  • The server sends the types of certificate it will accept.   This is typically RSA, DSA, and EC
  • The server sends down the Elliptic Curve names it will accept, if present  – I dont think it is used on the java client
  • The server uses the jdk.certpath.disabledAlgorithm to filter the list of Signature Algorithms, and sends this filtered list to the client.
  • The server extracts the CAs and self signed certificates from the trust store and sends them down to the client.
  • The server sends “ServerHelloDone”, saying over to you to respond.

Client processing:

  • Checks the server’s certificate is valid, including
    • Checks the public certificate of the servers CA chain is allowed according to the client’s jdk.certpath.disabledAlgorithm..  So jdk.certpath.disabledAlgorithm =…, SHA256withECDSA would not allow a  server’s certificate with Signature algorithm:SHA256withECDSA .
  • The client takes the list of certificate types ( RSA, DSA, EC), and CAs and iterates over the keystore and selects the records where
    • the certificate type in the list
    • the signature algorithm is in the list
    • the certificate signed by one of the CA’s in the list
  • Displays this list for the end user to select from.  It looks like the most recently added certificate is first in the list.
  • The client sends “Finished” and  the selected certificate to the server

Server processing

  • The server checks the certificate and any imbeded CA certificates from the client matches.
    • Checks the signature algorithm
    • Checks the constraints, for example RSA keySize < 2048
    • Checks the certificate and CA are valid

End of handshake.

 

This is a useful link for describing the java.security parameters.

This specification  describes the handshake, with the “ClientHello” etc.

How to stop weak people from accessing your web server (liberty) and mqweb

In the ongoing security battle arena, standards of protection are improving.  What may have been an acceptable cipher suite last year may be less acceptable today.  For many years a RSA certificate was considered the best.  Now certificates using Elliptic Curves are considered superior as they require smaller keys for the same level of protection, are harder to break, and use less CPU when they are used.

Google wants to have digital certificates renewed every year rather than the two years it tends to be today.  (From what I have read Certificate Authorities certificates can be around for years).

Your security team should be updating the user certificates regularly, so this should not be your problem.  You need to review your servers and do regular “housekeeping” to bring them inline with current best practice.  It is easy to forget a service which just sits there and runs, and so is a weak entry point to your environment.

The house keeping tasks:

  1. Ensuring your Certificate Authority certificates use current options: type of certificate, key size etc.
  2. Ensure the server’s certificate uses current options
  3. You restrict what certificates can be used to connect to the server.  For example do not allow RSA certificate with RSA with a small key size.

Renewing certificates

In some enterprises you have one certificate which identifies you, and then have controls within each server which manage which users are allowed to connect.  In other enterprises you may have a general certificate, plus a certificate for “monitoring” which has been signed by the “monitoring CA”.  This makes it easier to control access – if your certificate does not have the “monitoring CA” you do not get into the server.

If you are an enterprise you are likely to have a process which automatically renews individual’s certificates.  This is likely to be “go on-site, plug into the ethernet, ( so people cannot intercept your wireless), get  a new certificate”.   It is harder to renew your server’s certificates.

You will need steps along the lines of

  • Strengthen your CA if required
    • Generate a new, stronger, CA certificate;   for example using Elliptic Curves instead of RSA
    • Every machine needs to install the new CA certificate in the trust stores/browsers, alongside the old CA certificate.  You need a period when both CA certificates are available to allow for a transition period, as you need to change both ends of the TLS connection.
    • You can now deploy new individual certificates with their CA, to your users which go into their key store. Users connecting to a server with the new certificates will be validated with the  server’s new CA. Users which have certificates with the old CA will continue to use the old CA.
  • You need a new certificate for your web server.  If this is using the new CA, then all end users will need to have the new CA in their trust store, so the web server certificate can be validated.  If you are not using a new CA, then the existing CA can be used with no change.
  • Once all the users have their new certificate, you can remove the old CA from the server and from the user’s trust stores/browsers.  If a user tries to use the old certificate, if will fail to verify as the CA is no longer present.

Restricting what certificates and cipher suites can be used.

You can configure java security to restrict the certificates and cipher suites are used.  For example enforce no RSA certificate, or RSA certificate with a key sizes < 2048 cannot connect to the web server.  You configure java.security.  See here.

(Not) Using TLS 1.3

The TLS standards are being improved, for example TLS 1.3 protocol has improved algorithms, which are faster and more secure than in TLS 1.2.  The handshake has been improved, and weak algorithms have been dropped.   Most browsers already support TLS v1.3.

In theory this is a simple matter of changing the protocol parameter from TLSv1.2 to TLSv1.3 and it will all magically work.  This support is in java release 11.  Unfortunately the java used by mqweb is not at this level (it it java version 8) so cannot support it.   This means you have to make the changes yourself.

Change it, pray, answer the phone, and backout the change.

In an ideal world your server would produce a report of which certificates were used, with the Distinguished Name(the owner), what algorithms are used, and what CAs are used.  You make a note of all those which need attention, get the certificates upgraded, and when all the certificates are good – you can enable the stronger functions and it will all work first time.

I have not been able to get this list from my servers.

What I expect will happen as you enable the stronger functions, is that people who are not ready, will stop working, and will report problems.   You turn off the stronger functions, fix the machines which had problems and repeat until the phone stops ringing.
Some changes, for example changing java -D…. options in the jvm.options will require a server restart.  Other changes within the mqwebuser.xml, may get picked up periodically (and so avoids the need to restart the server), but you may need to restart the server.  On my laptop it takes over 10 seconds to stop and restart the server.

This upgrade process is very disruptive and does not provide a highly available server your enterprise needs.  Think how many change requests you will need to submit before it all works!  The best solution is to start with a very secure web server.

Using java -Djavax.net.debug=… to examine data flows, including TLS

There are different levels you can get from the -Djavax.net.debug option.  You can display its options using -Djavax.net.debug=help .

With this you get

all            turn on all debugging
ssl            turn on ssl debugging

The following can be used with ssl:

    record       enable per-record tracing
    handshake    print each handshake message
    keygen       print key generation data
    session      print session activity
    defaultctx   print default SSL initialization
    sslctx       print SSLContext tracing
    sessioncache print session cache tracing
    keymanager   print key manager tracing
    trustmanager print trust manager tracing
    pluggability print pluggability tracing

    handshake debugging can be widened with:
    data         hex dump of each handshake message
    verbose      verbose handshake message printing

    record debugging can be widened with:
    plaintext    hex dump of record plaintext
    packet       print raw SSL/TLS packets

 

and your program exits.

You can use

-Djavax.net.debug=ssl:record or -Djavax.net.debug=ssl:handshake

To display specific levels of detail.

How do I create a certificate with Elliptic Curve (or RSA)

Why would I want to use Elliptic Curve?

Some ciphers are considered stronger than others.  For example certificates with Elliptic Curve algorithms are now considered better than using the well known RSA.    They are more secure and use less resources.  Over time certificates with Elliptic Curves may become the norm.  See here.

If you change to use a different algorithm you need to make sure that both ends of the TLS connection support it.   If a cipher spec beginning with TLS_ECDHE is the only cipher spec available, it may not work with certificates with RSA.

When you create a certificate you first create the private key, and then make the public certificate.  You can sometimes combine this into one operation.

To make a private key using Elliptic Curve

Use

openssl genpkey -out $name.key.pem -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes256 -pass file:password.file

where

  • $name – I create the certificate in a shell script.  As the name of the certificate is used in many places – it is best to use a shell variable to hold the short certificate name.
  • -algorithm EC says this is an Elliptic Curve
  •  P-256  is the Elliptic Curve definition to use.   This is a popular key;  it has a key length of 256.  It is also known as prime256v1.
  • -aes256 -pass file:password.file says encrypt the private key using the aes 256 cipher spec (there are others available) – and use the password in the file. You need this when doing working with private key and public certificate, for example creating the certificate request.  If you do not specify -aes256 (or equivilant)  etc the private key is not encrypted, and so could be used if stolen.   This is not used during TLS handshakes.

Or (the old syntax )

openssl ecparam -name prime256v1 -genkey -noout -out $name.key.pem …

You then create the request and get the request signed (this is common to all requests)

name=”eccert”
openssl req -config xxx.config -new -key $name.key.pem -out $name.csr -outform PEM -subj “/C=GB/O=cpwebuser/CN=”$name -passin file:password.file -passout file:password.file
openssl ca -config openssl-ca-user.cnf -policy signing_policy  -md sha256 -cert ca2.pem -keyfile ca2.key.pem -out $name.pem -in $name.csr  -extensions clientServer

The command openssl x509 -in eccert.pem -text -noout|less displays the certificate and gives

Subject Public Key Info:
  Public Key Algorithm: id-ecPublicKey
    Public-Key: (256 bit)
     pub:
       04:...
       ce:60:63:03:84
     ASN1 OID: prime256v1
     NIST CURVE: P-256

During the TLS handshake, this can be processed by CipherSpecs TLS_EC*, such as TLS_ECDH… and TLS_ECDHE…

If you use openssl ecparam -name secp521r1  this gives Public Key Algorithm: id-ecPublicKey Public-Key: (521 bit)

To make a private key using RSA

Use

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out $name.key.pem -aes256 -pass pass:password

Or (the old syntax)

openssl genrsa -out $name.key.pem 4096 -aes256 -pass pass:password

where

  • rsa_keygen_bits:4096  – is the size of the key to use.
  • -aes256 -pass pass:password says encrypt the private key  using the aes 256 cipher spec (there are others available) – the password is password.  You need this when doing working with private key and public certificate.  This is not used during TLS handshakes.

You make the request and get it signed (the statements below are the same as for the EC certificate)

name=”rsa”
ca=”ca2″
openssl req -config xxx.config -new -key $name.key.pem -out $name.csr -outform PEM -subj “/C=GB/O=cpwebuser/CN=”$name -passin file:password.file -passout file:password.file
openssl ca -config openssl-ca-user.cnf -policy signing_policy  -md sha256 -cert $ca.pem -keyfile $c2.key.pem -out $name.pem -in $name.csr  -extensions clientServer

The command openssl x509 -in rsa.pem -text -noout|less displays the certificate and gives

Subject Public Key Info:
  Public Key Algorithm: rsaEncryption
   RSA Public-Key: (4096 bit)
    Modulus:
      00:d0:88:d2:d0:86:34:82:bb:1a:7b:a0:6d:37:fd:
      ... 
     1e:3d:31
    Exponent: 65537 (0x10001)

During the TLS handshake, this can be processed by CipherSpecs TLS_RSA*.

Changing the Signature Algorithm:

With a java program, you can use java.security to limit which Security Algorithms are allowed during the handshake, and so prevent certificates from being used.

As part of the TLS handshake there is a conversation about the encryption of the certificate.  For example listing an RSA certificate gives

Signature Algorithm: sha256WithRSAEncryption

You can change this by using

openssl ca … -md sha384

This gives

Signature Algorithm: sha384WithRSAEncryption

For an Elliptic Curve certificate this was

Signature Algorithm: ecdsa-with-SHA256  with the default -md (sha256) or Signature Algorithm: ecdsa-with-SHA384 ( when -md sha384 is specified)

Storing the certificate

I used a script to generate my certificate.  In this script I had

  • openssl x509 -in $name.pem -text -noout|less to display the certificate, and check the options
  • openssl pkcs12 -export -inkey $name.key.pem -in $name.pem -out $name.p12 -CAfile ca256.pem -chain -name $name -passout file:password.file -passin file:password.file to create the *.p12 file with the certificate and CA chain, so it can be used by java, and curl etc
  • certutil -D $sql -n $name remove the certificate from the Chrome browser keystore.  Where sql=”-d sql:/home/colinpaice/snap/chromium/current/.pki/nssdb”
  • pk12util -i $name.p12 $sql -W password to add the  .p12 created above into the Chromium keystore (along with its CA chain)

Using the certificate

For my java programs I used the certificate keystore sssks.p12 with -Djavax.net.ssl.keyStore=/home/colinpaice/ssl/ssl2/sssks.p12 -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.keyStoreType=pkcs12 or for mqwebuser.xml  <keyStore id=”defaultKeyStore” location=”/home/colinpaice/ssl/sssks.p12″ type=”pkcs12″ password=”password”/>

Should I specify which cipher suites my web browser should use – or the opposite?

I was investigating how to upgrade the certificate used by my mqweb server from RSA to the new, improved, Elliptic Curve, and wondered how to make it most secure.
At first I thought the answer to the question was yes, then I changed my mind to no, then I changed to yes, and now I think you should do something else!

The short answer is you should not specify which cipher specs to use, but you may considering saying which ones not to use by overriding java.security features.

SSL and TLS Deployment Best Practices covers many good topics.

The first part of the TLS handshake

  • The client sends a list of the cipher suites it supports to the server
  • The serve has its own list (which you can influence)
  • The server takes each cipher suite in turn from the client list, and selects the first one which is in the server’s list and matches the server’s certificate
  • If the server is using an RSA certificate, then cipher suites with TLS_…RSA_WITH… are used. With Elliptic Curve certificates then TLS_….ECDSA_WITH… are used.

When using Chrome to talk to my java server the certificate suites sent up were

  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, strong
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 strong
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 very strong
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384  strong
  • SSL_RSA_WITH_3DES_EDE_CBC_SHA weak

These go from strong to weak.  Certificates with 3DES or _SHA are considered too weak to use.

My java server had the following cipher suites

  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
  • TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
  • TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
  • ….

And the final cipher suite chosen was

TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 – top of the list from the client and 29th in the list in the server – not the strongest certificate in the list which was a surprise.

Specifying a server cipher suite.

You can specify the list of cipher suites used by the server using the java property -Djdk.tls.server.cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,…
So yes;  you can specify a list of cipher specs, and the order, and so put the “strongest first”.

I then asked myself is the default one TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 any better than the  “best one” TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384?

Bulk data encryption.

Looking on the internet, there is a general feeling that there is no significant difference between AES_128 and AES_256.  If quantum computers become a reality, then there may be benefits of AES_256, but then the whole of the encryption world will have changed.

AES…GCM is better than AES…CBC.  The difference between them is not so clear.  GCM is considered better than CBC, it can run on pipeline processors, but may use more CPU overall.  Both have weaknesses, but different weaknesses.

Hashing algorithm

I looked at the hashing algorithm, again there was not much difference between SHA256, SHA 384 and SHA512.
I did some evaluation on the use of SHA256 and SHA512 on my laptop using the command openssl speed sha256 sha512. This hashes different sized buffers and calculates bytes processed per second.

type    16 bytes   64 bytes  256 bytes 1024 bytes 16384 bytes
sha256 70348.86k 158677.42k 297724.76k 370884.61k 400878.25k
sha512 49354.44k 195907.78k 341598.21k 507424.77k 597409.79k

So we can see with very small buffers SHA 256 could do 70 MB/second, and SHA512 could only do 49 MB/second, but with bigger buffers SHA256 did 40MB/second, and SHA512 did 59 MB/second

It looks like there is no significant difference between them.

Note: when they upgraded SHA256 to SHA512 they improved the algorithm as well as the number of iterations. This applies to other algorithms as well.

Overall  the default TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 is as good as the “best one” TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, and so there was no advantage in specifying a cipher suite.

Other advantages of not specifiying a cipher suite

Last year you may have specified the then best cipher suite.   This year there are new, better, cipher suites which are the default.  If you specified the cipher suite you will use last year’s suite.

When your web server supports TLSv1.3 ( dependent on java 11) it will use a different set of cipher suites.  By not specifying a cipher suite name, the migration will be easier.  Today browsers already support TLS v1.3 and send up a mixture of cipher suites for TLSv1.2 and TLS v1.3 as part of the TLS handshake.

Do not specify the cipher suite – specify what you do not want.

You can specify security information to java using a java.security file.  See here.  You can override this file using a system parameter like -Djava.security.properties=/home/colinpaice/eclipse-workspace-C/sslJava/bin/serverdisabled.properties.

In this file you can specify

jdk.tls.disabledAlgorithms=…
jdk.certpath.disabledAlgorithms= …

You specify what do you not want.

The defaults are

  • jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
  • jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024,EC keySize < 224, 3DES_EDE_CBC

You could specify RSA keySize < 2048, so any cipher suites and certificate using an RSA key size of under 2048 would not be allowed.