Closed cemeyer closed 5 years ago
These Vary Speshul MAC Functions are so utterly solution-in-search-of-a-problem that I sorta doubt anyone is using the sha256
versions.
I presume that RSA really wants to use AES-based MAC because they make a bunch of hardware devices that can't really do anything except AES. Their software token only offers up the AES version in the list of algorithms it supports … so I wouldn't spend much time on the SHA256 version.
The RFC doesn't even contain test vectors for the CT-KIP-PRF-AES function. :thumbsdown:
These are really PRFs, not MACs, right?
Sounds like we can just drop SHA for now; it's a pretty trivial extension of the same algorithm.
I have no idea what RSA is doing with them, though. I noticed the RFC lacked test vectors :-(.
These are really PRFs, not MACs, right?
It's sort of unclear. The RFC really wants to call it a MAC.
Here's a slightly-commented version of the interesting parts of the client/server exchange, from my fakeserver.py, after removing the topmost layer of crud (base64 the whole XML doc, wrap it in SOAP).
<ClientHello xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/11/ct-kip#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.0">
<SupportedKeyTypes xmlns="">
<Algorithm xsi:type="xsd:anyURI">http://www.rsasecurity.com/rsalabs/otps/schemas/2005/09/otps-wst#SecurID-AES</Algorithm>
</SupportedKeyTypes>
<SupportedEncryptionAlgorithms xmlns="">
<Algorithm xsi:type="xsd:anyURI">http://www.w3.org/2001/04/xmlenc#rsa-1_5</Algorithm>
</SupportedEncryptionAlgorithms>
<SupportedMACAlgorithms xmlns="">
<Algorithm xsi:type="xsd:anyURI">http://www.rsasecurity.com/rsalabs/otps/schemas/2005/11/ct-kip#ct-kip-prf-aes</Algorithm>
</SupportedMACAlgorithms>
</ClientHello>
<ServerHello xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SessionID="{sess}" Status="Continue" Version="1.0">
<KeyType xmlns="">http://www.rsasecurity.com/rsalabs/otps/schemas/2005/09/otps-wst#SecurID-AES</KeyType>
<EncryptionAlgorithm xmlns="">http://www.w3.org/2001/04/xmlenc#rsa-1_5</EncryptionAlgorithm>
<EncryptionKey xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ds:KeyValue xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Server sends a 1024-byte RSA pubkey -->
<ds:RSAKeyValue xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ds:Modulus>{mod}</ds:Modulus>
<ds:Exponent>{exp}</ds:Exponent>
</ds:RSAKeyValue>
</ds:KeyValue>
</EncryptionKey>
<Payload xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Server sends a 16-byte nonce -->
<Nonce xmlns="">{rb}</Nonce>
</Payload>
<Extensions xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Extension xmlns:ct-kip="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Server repeats the same 16-byte nonce here -->
<Data>{rb}</Data>
</Extension>
</Extensions>
<MacAlgorithm xmlns="">http://www.rsasecurity.com/rsalabs/otps/schemas/2005/11/ct-kip#ct-kip-prf-aes</MacAlgorithm>
</ServerHello>
<ClientNonce xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/11/ct-kip#" Version="1.0" SessionID="$SESSIONID">
<EncryptedNonce xmlns="">
base64( PKCS #1 OAEP encypt( RSA public key sent by server, 16-byte client nonce ) )
</EncryptedNonce>
<Extensions xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Extension xmlns="" xmlns:ct-kip="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This simply echoes the value sent previously by the server -->
<Data>base64(16-byte server nonce)</Data>
</Extension>
</Extensions>
</ClientNonce>
<ServerFinished xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SessionID="{sess}" Status="Success" Version="1.0">
<TokenID xmlns="">{tid}</TokenID>
<KeyID xmlns="">{tid}</KeyID>
<KeyExpiryDate xmlns="">{exp}</KeyExpiryDate>
<ServiceID xmlns="">RSA CT-KIP</ServiceID>
<UserID xmlns=""/>
<Extensions xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Extension xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Critical="true">
<OTPFormat>Decimal</OTPFormat>
<OTPLength>8</OTPLength>
<OTPMode xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Time xmlns="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" TimeInterval="60"/>
</OTPMode>
</Extension>
</Extensions>
<Mac xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" MacAlgorithm="http://www.rsasecurity.com/rsalabs/otps/schemas/2005/12/ct-kip#ct-kip-prf-aes">
<!-- This is where all the securiteh goes -->
{rmb}
</Mac>
</ServerFinished>
So here's what RFC4758 has to say about this MAC:
https://tools.ietf.org/html/rfc4758#section-3.8.6:
: To avoid a false "Commit" message causing the token to end up in an initialized state for which the server does not know the stored key, messages must always be authenticated with a MAC. The MAC shall be made using the already established MAC algorithm. The MAC value shall be computed on the (ASCII) string "MAC 2 computation" and R_C using an authentication key K_AUTH. Again, this should be a special authentication key used only for this purpose, but may also be an existing K_TOKEN. (In this case, implementations must protect against attacks where K_TOKEN is used to pre-compute MAC values.) **If no authentication key is present in the token, and no K_TOKEN existed before the CT- KIP run, K_AUTH shall be the newly generated K_TOKEN.** If CT-KIP-PRF is used as the MAC algorithm, then the input parameter s shall consist of the concatenation of the (ASCII) string "MAC 2 computation" and R_C, and the parameter dsLen shall be set to the length of R_C: dsLen = len(R_C) MAC = CT-KIP-PRF (K_AUTH, "MAC 2 computation" || R_C, dsLen) When receiving a message with Status = "Success" for which the MAC verifies, the CT-KIP client shall associate the generated key K_TOKEN with the provided key identifier and store this data permanently. After this operation, it shall not be possible to overwrite the key unless knowledge of an authorizing key is proven through a MAC on a later (and ) message. The CT-KIP client must verify the MAC. The CT-KIP client must terminate the CT-KIP session if the MAC does not verify, and must, in this case, also delete any nonces, keys, and/or secrets associated with the failed run of the CT-KIP protocol. The MacType's MacAlgorithm attribute shall, when present, identify the negotiated MAC algorithm.
where (https://tools.ietf.org/html/rfc4758#section-2.2):
K_AUTH Secret key used for authentication purposes K_TOKEN Secret key used for token computations, generated in CT-KIP
My interpretation of the bolded part is that, when creating a new token, the key used for the MAC K_AUTH
is the same as the key value used in the token itself at the conclusion of the exchange K_TOKEN
.
Except that this diagram (Figure 2 in https://tools.ietf.org/html/rfc4758#section-3.3) suggests that the server's public key, and the client and server nonces (R_C
and R_S
) should be enough to derive the key.
+----------------------+ +-------+ +----------------------+
| +------------+ | | | | |
| | Server key | | | | | |
| +<-| Public |------>------------->-------------+---------+ |
| | | Private | | | | | | | |
| | +------------+ | | | | | | |
| | | | | | | | | |
| V V | | | | V V |
| | +---------+ | | | | +---------+ | |
| | | Decrypt |<-------<-------------<-----------| Encrypt | | |
| | +---------+ | | | | +---------+ | |
| | | +--------+ | | | | ^ | |
| | | | Server | | | | | | | |
| | | | Random |--->------------->------+ +----------+ | |
| | | +--------+ | | | | | | Client | | |
| | | | | | | | | | Random | | |
| | | | | | | | | +----------+ | |
| | | | | | | | | | | |
| | V V | | | | V V | |
| | +------------+ | | | | +------------+ | |
| +-->| CT-KIP PRF | | | | | | CT-KIP PRF |<----+ |
| +------------+ | | | | +------------+ |
| | | | | | | |
| V | | | | V |
| +-------+ | | | | +-------+ |
| | Key | | | | | | Key | |
| +-------+ | | | | +-------+ |
| +-------+ | | | | +-------+ |
| |Key Id |-------->------------->------|Key Id | |
| +-------+ | | | | +-------+ |
+----------------------+ +-------+ +----------------------+
CT-KIP Server CT-KIP Client CT-KIP Client (Token)
(PC Host)
Figure 2: Principal data flow for CT-KIP key generation - using
public server key
This diagram seems to totally contradict the claims elsewhere in the document that the key for the PRF is a secret key, since the key being used here for the PRF is an RSA public key… :man_facepalming:
It's sort of unclear. The RFC really wants to call it a MAC.
The PRF also sometimes calls the PRF an encryption algorithm, too. I don't know what they are thinking.
Yeah I am facepalming over here too :-).
Edit: I posted some highlighted RFC excerpts on the earlier gist as well. The RFC documents several different salts for different steps of the negotiation; I'm not sure if those are the same ones the product uses.
The RFC documents several different salts for different steps of the negotiation
The RFC is a dumpster fire. Is this thing really an "internet standard"?
And thanks, responding to your useful comments on the gist now.
The RFC is a dumpster fire. Is this thing really an "internet standard"?
I guess not!
This memo provides information for the Internet community. It does not specify an Internet standard of any kind.
:joy:
We ended up just doing this in Python with @dlenski's ct-kit.py, but if someone ever wants to integrate that key negotiation protocol into stoken
natively, this code (or similar) could be a useful component.
Add totally untested implementations of the OMAC1-AES ("CMAC") and CT-KIP-PRF-* family of pseudo-random functions per relevant RFCs. It compiles but that's about all I've tested.
Broken:
Re: #27
(Not necessarily useful to pull as-is, but may be useful as a starting place.)