Subject Confirmation support with Apache Rampart : Holder-of-Key

The Subject Confirmation is the process of establishing the correspondence between the subject and claims of SAML statements (in SAML assertions) and SOAP message content by verifying the confirmation evidence provided by an attesting entity.

SAML 1.1 Token Profile talks about three subject confirmation methods.

1. Holder-of-key Subject Confirmation Method
2. Bearer-key Subject Confirmation Method
2. Sender-vouches Subject Confirmation Method

With Holder-of-key Subject Confirmation Method, the attesting entity demonstrates that it is authorized to act as the subject of a holder-of-key confirmed SAML statement by demonstrating knowledge of any key identified in a holder-of-key SubjectConfirmation element associated with the statement by the assertion containing the statement. Statements attested for by the holder-of-key method MUST be associated, within their containing assertion, with one or more holder-of-key SubjectConfirmation elements.

Let's see how this works..

First the client application needs to request a token from the Security Token Service or the STS. This request is known as RST [wst:RequestSecurityToken] and goes inside the SOAP Body. Following is a sample RST.

   http://schemas.xmlsoap.org/ws/2005/02/trust/Issue
   
   
    
     http://localhost:8280/services/echo
    
   
   
    2011-11-15T10:29:17.487Z
    2011-11-15T10:34:17.487Z
   
   http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1
   
   http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey
   
   256
   
    nVY8/so9I3uvI3OSXDcyb+9kxWxMFNiwzT7qcsr5Hpw=
    
   
   http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1
   
  
Let's have a look at some of the key elements in the RST.

1. AppliesTo

This is the end point where the client going to use this token against.

2. KeyType : http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey

Use Symmetric key when generating the key for the SubjectConfirmation.

3. KeySize

Use this key size when generating the key for the SubjectConfirmation.

4. Entropy/BinarySecret

WS-Trust allows the requestor to provide input to the key material via a wst:Entropy element in the request. The requestor might do this to satisfy itself as to the degree of entropy (cryptographic randomness if you will) of at least some of the material used to generate the actual key which is used for SubjectConfirmation.

5. Entropy/ComputedKeyAlgorithm : http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1

The key derivation algorithm to use if using a symmetric key for P, where P is computed using client, server, or combined entropy.

With http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1 the key is computed using P_SHA1 from the TLS specification to generate a bit stream using entropy from both sides. The exact form is:
key = P_SHA1 (EntREQ, EntRES)
It is RECOMMENDED that EntREQ be a string of length at least 128 bits.

Now let's see how this request been processed at the STS end.

Based on the Key Type in the request - STS will decide whether to use Holder-of-key or not. For following key types, holder-of-key subject confirmation method will be used.

1. http://docs.oasis-open.org/ws-sx/ws- trust/200512/PublicKey
2. http://docs.oasis-open.org/ws-sx/ws- trust/200512/SymmetricKey

If it is SymmetricKey - then STS will generate a key - encrypt the key using the public certificate corresponding to the end point attached to the AppliesTo element in the RST and add that to the SubjectConfirmation element in the response.

Key generation is once again bit tricky.

If client provides an entropy and the key computation algorithm is http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1 then, the key is generated as a function of the client entropy and the STS entropy.

If client provides an entropy but the key computation algorithm is NOT http://schemas.xmlsoap.org/ws/2005/02/trust/CK/PSHA1 then, the key is same as the client entropy.

If neither of above happens, then the server generates an ephemeral key.

Whatever the way the key is generated, it will be encrypted with the certificate corresponding to the AppliesTo end point and will be added in to the SubjectConfirmation element in the response.

        urn:oasis:names:tc:SAML:1.0:cm:holder-of-key
        
        
         
          
          
           
            Ye9D13/K1GFRvJjgw1kSr5/rYxE=
           
          
          
           a/kALeV0b0Y3oNcE7fdepUuF0sbQUGs012r87BMBUx/FL8Hc+kw/BGrRThEGGmDmVgJ8GdJw34nQM6IjulNV+hj/MmtXLSKZnjm7uLPPT3kgT0udzc8OuSgLVRO8ghcDK12/IiPAtzWZIfPS/ZT8kx4DSYWnvcNa4mTMM4wBhjt29bvAJcKZD0CqvJOLIFWc2FrQqNkym4UIF+GEcsN3rQcYDzoyiCm2L4RAm3u+1d+9zsQIEo8DtqDDboA0MAVbbM6xU3JbF35dLifmpwlsuiJC0y8VlAoN6wnNIJ/tpr4C4FhvdKnShAOeDf3D2JkZxr4ZNZZL91aHFaPpFbC9YQ==
           
          
         
        
       
As per the above code, what you see inside CipherValue element is the encrypted key. And it is encrypted from a certificate which is having the thumbprint reference Ye9D13/K1GFRvJjgw1kSr5/rYxE=. In other words, only the service which owns the certificate having the thumbprint reference Ye9D13/K1GFRvJjgw1kSr5/rYxE= would be able to decrypt the key - which is in fact the service end point attached to the AppliesTo element. BTW... can anybody in the middle fool the service endpoint just by replacing the SubjectConfirmation element..? This is prevented by STS signing the SubjectConfirmation element along with Assertion parent element with it's private key. So - the SAML token is protected for integrity.

Okay... now the token is at the client end... In which ways the client application going to use this token.

One way is to use it as a SupportingToken and the other way is to use it as a ProtectionToken.

When we use SAML token as a ProtectionToken, client application can use it to encrypt/sign the messages going from the client to the service end point. Then the question is which key would the client use to sign and encrypt - it's the same key added to the SubjectConfirmation by the STS - but it's encrypted with the public key of the service end point - so, client won't be able to decrypt it and get access to the hidden key.

There is another way, STS passes the generated key to the client. Let's look at the following element also included in the response passed from the STS to the client - this is out side the Assertion element.
<wst:Entropy>
    <wst:BinarySecret
     Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">3nBXagllniQA8UEAs5uRVJFrKb9dPZITK76Xk/XCO5o=
    </wst:BinarySecret>
   </wst:Entropy>
Here in the Entropy/BinarySecret STS passed the entropy created to generate the key. The key is generated as a function of the client entropy and the STS entropy - client already knows the client entropy and can find the STS entropy inside Entropy/BinarySecret in the response - so, client can derive the key from those.

Following would be the WS-Security Policy at the service end, which expects SAML token as a ProtectionToken.
<wsp:Policy wsu:Id="SgnOnlyAnonymous"
 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
 xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:SymmetricBinding>
    <wsp:Policy>
     <sp:ProtectionToken>
      <wsp:Policy>
       <sp:IssuedToken
        sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
        <Issuer xmlns="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
         <Address xmlns="http://www.w3.org/2005/08/addressing">http://localhost:8080/axis2/services/STS
         </Address>
        </Issuer>
        <sp:RequestSecurityTokenTemplate>
         <t:TokenType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1
         </t:TokenType>
         <t:KeyType xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey
         </t:KeyType>
         <t:KeySize xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">256</t:KeySize>
        </sp:RequestSecurityTokenTemplate>
        <wsp:Policy>
         <sp:RequireInternalReference />
        </wsp:Policy>
       </sp:IssuedToken>
      </wsp:Policy>
     </sp:ProtectionToken>
     <sp:AlgorithmSuite>
      <wsp:Policy>
       <sp:Basic128 />
      </wsp:Policy>
     </sp:AlgorithmSuite>
     <sp:Layout>
      <wsp:Policy>
       <sp:Lax />
      </wsp:Policy>
     </sp:Layout>
     <sp:IncludeTimestamp />
     <sp:OnlySignEntireHeadersAndBody />
    </wsp:Policy>
   </sp:SymmetricBinding>
   <sp:SignedParts>
    <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing" />
    <sp:Body />
   </sp:SignedParts>
   <sp:Wss11>
    <wsp:Policy>
     <sp:MustSupportRefKeyIdentifier />
     <sp:MustSupportRefIssuerSerial />
     <sp:MustSupportRefThumbprint />
     <sp:MustSupportRefEncryptedKey />
     <sp:RequireSignatureConfirmation />
    </wsp:Policy>
   </sp:Wss11>
   <sp:Trust10>
    <wsp:Policy>
     <sp:MustSupportIssuedTokens />
     <sp:RequireClientEntropy />
     <sp:RequireServerEntropy />
    </wsp:Policy>
   </sp:Trust10>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>
When we use the SAML token as a SupportingToken, we basically doing nothing from it that sending it as it is to the service end in the SOAP Security Header. SubjectConfirmation goes useless here - but service end can verify whether the token been issued by a trusted STS, by verifying the signature.

Following is the WS-Security Policy at the service end - which expects SAML token as a SupportingToken.
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
 wsu:Id="SigEncr">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:SupportingTokens
    xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
    <wsp:Policy>
     <sp:IssuedToken
      sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
      <Issuer xmlns="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
       <Address xmlns="http://www.w3.org/2005/08/addressing">
        https://localhost:9443/services/wso2carbon-sts
       </Address>
      </Issuer>
      <sp:RequestSecurityTokenTemplate
       xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
       <t:TokenType>
        urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
       <t:KeyType>
        http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey
       </t:KeyType>
       <t:KeySize>256</t:KeySize>
       <t:Claims Dialect="http://wso2.org/claims"
        xmlns:ic="http://schemas.xmlsoap.org/ws/2005/05/identity">
        <ic:ClaimType Uri="http://wso2.org/claims/givenname" />
       </t:Claims>
      </sp:RequestSecurityTokenTemplate>
      <wsp:Policy>
       <sp:RequireInternalReference />
      </wsp:Policy>
     </sp:IssuedToken>
    </wsp:Policy>
   </sp:SupportingTokens>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>