RFC 2025
The Simple Public-Key GSS-API Mechanism (SPKM)
Hiii, Let's Get Into RFC 2025 ๐
Okay bestie, this one is The Simple Public-Key GSS-API Mechanism (SPKM) ๐ It's by C. Adams at Bell-Northern Research, dated October 1996, and it's on the Standards Track ๐ฆ The header doesn't list anything it obsoletes or updates, so it's a standalone vibe ๐
Status of This Memo โจ
This doc is an Internet standards track protocol for the Internet community, and it's literally asking for discussion and suggestions for improvements ๐ซถ For the standardization state and status of this protocol, check the "Internet Official Protocol Standards" (STD 1) ๐ Distribution of this memo is unlimited ๐
Abstract ๐
This spec defines protocols, procedures, and conventions that peers are meant to employ when they're implementing the Generic Security Service Application Program Interface (as specified in RFCs 1508 and 1509) and using the Simple Public-Key Mechanism ๐ง
Background ๐
The Kerberos Version 5 GSS-API mechanism [KRB5] is becoming super established in lots of environments ๐ฅ But in some apps it matters a lot to have a GSS-API mechanism that's based on a public-key infrastructure instead of a symmetric-key one ๐ The mechanism in this doc was proposed to meet that need and to give you these features:
- The SPKM allows both unilateral and mutual authentication to be accomplished without the use of secure timestamps. This enables environments which do not have access to secure time to nevertheless have access to secure authentication. ๐ฐ๏ธ๐ซ
- The SPKM uses Algorithm Identifiers to specify various algorithms to be used by the communicating peers. This allows maximum flexibility for a variety of environments, for future enhancements, and for alternative algorithms. ๐ธ
- The SPKM allows the option of a true, asymmetric algorithm-based, digital signature in the gss_sign() and gss_seal() operations (now called gss_getMIC() and gss_wrap() in [GSSv2]), rather than an integrity checksum based on a MAC computed with a symmetric algorithm (e.g., DES). For some environments, the availability of true digital signatures supporting non-repudiation is a necessity. โ๏ธ๐
- SPKM data formats and procedures are designed to be as similar to those of the Kerberos mechanism as is practical. This is done for ease of implementation in those environments where Kerberos has already been implemented. ๐ฆ
For the above reasons, it is felt that the SPKM will offer flexibility and functionality, without undue complexity or overhead. Honestly iconic ๐
Key Management ๐๏ธ
The key management in SPKM is meant to be as compatible as possible with both X.509 [X.509] and PEM [RFC-1422], since these represent large communities of interest and show relative maturity in standards ๐
Acknowledgments ๐
A lot of this doc is based on the Kerberos Version 5 GSS-API mechanism [KRB5], and it's meant to be as compatible with it as possible ๐ซถ The authors also owe a huge thank-you to Warwick Ford and Paul Van Oorschot of Bell-Northern Research for many fruitful discussions, to Kelvin Desplanque for implementation-related clarifications, to John Linn of OpenVision Technologies for helpful comments, and to Bancroft Scott of OSS for ASN.1 assistance ๐
1. Overview โจ
The goal of the Generic Security Service Application Program Interface (GSS-API) is stated in the abstract of [RFC-1508] like this:
"This Generic Security Service Application Program Interface (GSS-
API) definition provides security services to callers in a generic
fashion, supportable with a range of underlying mechanisms and
technologies and hence allowing source-level portability of
applications to different environments. This specification defines
GSS-API services and primitives at a level independent of
underlying mechanism and programming language environment, and is
to be complemented by other, related specifications:
- documents defining specific parameter bindings for particular
language environments;
- documents defining token formats, protocols, and procedures to
be implemented in order to realize GSS-API services atop
particular security mechanisms."
The SPKM is an instance of that second type of document, so it's termed a "GSS-API Mechanism" ๐ง This mechanism gives you authentication, key establishment, data integrity, and data confidentiality in an on-line distributed application environment using a public-key infrastructure ๐ Because it conforms to the interface defined by [RFC-1508], SPKM can be used as a drop-in replacement by any application that makes use of security services through GSS-API calls (for example, any application that already uses the Kerberos GSS-API for security) ๐ Using a public-key infrastructure lets digital signatures supporting non-repudiation be employed for message exchanges, and it brings other perks like scalability to large user populations ๐
The tokens defined in SPKM are meant to be used by application programs according to the GSS API "operational paradigm" (see [RFC-1508] for further details) ๐ง Here's how that paradigm is quoted:
The operational paradigm in which GSS-API operates is as follows.
A typical GSS-API caller is itself a communications protocol [or is
an application program which uses a communications protocol],
calling on GSS-API in order to protect its communications with
authentication, integrity, and/or confidentiality security
services. A GSS-API caller accepts tokens provided to it by its
local GSS-API implementation [i.e., its GSS-API mechanism] and
transfers the tokens to a peer on a remote system; that peer passes
the received tokens to its local GSS-API implementation for
processing.
This doc defines two separate GSS-API mechanisms, SPKM-1 and SPKM-2 ๐ฏ Their main difference is that SPKM-2 requires the presence of secure timestamps for replay detection during context establishment, while SPKM-1 does not. That gives apps more flexibility, since secure timestamps can't always be guaranteed to be available in a given environment โฐโจ
2. Algorithms ๐งฎ
A bunch of algorithm types are employed in SPKM. Each type, along with its purpose and a set of specific examples, is described in this section ๐ To make sure there's at least a minimum level of interoperability among various SPKM implementations, one of the integrity algorithms is specified as MANDATORY. All the remaining examples (and any other algorithms) may optionally be supported by a given SPKM implementation (note that a GSS-conformant mechanism need not support confidentiality) ๐ซถ Making a confidentiality algorithm mandatory may preclude exportability of the mechanism implementation, so this document specifies certain algorithms as RECOMMENDED. That means interoperability gets a boost if these algorithms are included in all SPKM implementations where exportability isn't a concern ๐
2.1 Integrity Algorithm (I-ALG):
Purpose:
This algorithm is used to ensure that a message has not been altered in any way after being constructed by the legitimate sender. Depending on the algorithm used, applying it may also provide authenticity and support non-repudiation for the message ๐ก๏ธ
Examples:
md5WithRSAEncryption OBJECT IDENTIFIER ::= {
iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1)
pkcs-1(1) 4 -- imported from [PKCS1]
}
This algorithm (MANDATORY) provides data integrity and authenticity and supports non-repudiation by computing an RSA signature on the MD5 hash of that data. It's essentially equivalent to md5WithRSA {1 3 14 3 2 3}, which is defined by OIW (the Open Systems Environment Implementors' Workshop) ๐
Since this is the only integrity/authenticity algorithm specified to be mandatory at this time, for interoperability reasons it's also stipulated that md5WithRSA be the algorithm used to sign all context establishment tokens which are signed rather than MACed. See Section 3.1.1 for details ๐ In future versions of this document, alternate or additional algorithms may be specified to be mandatory, and then this stipulation on the context establishment tokens may be removed ๐ฎ
DES-MAC OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) oiw(14) secsig(3)
algorithm(2) 10 -- carries length in bits of the MAC as
} -- an INTEGER parameter, constrained to
-- multiples of eight from 16 to 64
This algorithm (RECOMMENDED) provides integrity by computing a DES MAC (as specified by [FIPS-113]) on that data ๐
md5-DES-CBC OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) dod(6) internet(1)
security(5) integrity(3) md5-DES-CBC(1)
}
This algorithm provides data integrity by encrypting, using DES CBC, the "confounded" MD5 hash of that data (see Section 3.2.2.1 for the definition and purpose of confounding). It's typically faster in practice than computing a DES MAC, unless the input data is extremely short (e.g., a few bytes) โก Note that without the confounder, the strength of this integrity mechanism is (at most) equal to the strength of DES under a known-plaintext attack ๐จ
sum64-DES-CBC OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) dod(6) internet(1)
security(5) integrity(3) sum64-DES-CBC(2)
}
This algorithm provides data integrity by encrypting, using DES CBC, the concatenation of the confounded data and the sum of all the input data blocks (the sum computed using addition modulo 2**64 - 1). So in this algorithm, encryption is a requirement for the integrity to be secure ๐
For comments regarding the security of this integrity algorithm, see [Juen84, Davi89] ๐
2.2 Confidentiality Algorithm (C-ALG):
Purpose:
This symmetric algorithm is used to generate the encrypted data for gss_seal() / gss_wrap() ๐
Example:
DES-CBC OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) oiw(14) secsig(3)
algorithm(2) 7 -- carries IV (OCTET STRING) as a parameter;
} -- this (optional) parameter is unused in
-- SPKM due to the use of confounding
This algorithm is RECOMMENDED ๐
2.3 Key Establishment Algorithm (K-ALG): ๐
Purpose:
okay so K-ALG is the algorithm that sets up a symmetric key for both the initiator and the target over the established context ๐ซถ The keys for C-ALG and any keyed I-ALGs (like DES-MAC ๐ ) get derived from this context key. Section 3.1 explains that key establishment happens inside the X.509 authentication exchange, so the shared symmetric key comes out authenticated โจ
Examples:
Here's the first K-ALG, the RSA one:
RSAEncryption OBJECT IDENTIFIER ::= {
iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1)
pkcs-1(1) 1 -- imported from [PKCS1] and [RFC-1423]
}
In this algorithm (MANDATORY) ๐, the initiator generates the context key, encrypts it with the target's RSA public key, and sends it over. The target doesn't need to reply for the key to get established ๐
Next up is the key transport one:
id-rsa-key-transport OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) oiw(14) secsig(3)
algorithm(2) 22 -- imported from [X9.44]
}
It's basically the same vibe as RSAEncryption, but the source authenticating info is also encrypted with the target's RSA public key ๐ฅ
And then there's dhKeyAgreement:
dhKeyAgreement OBJECT IDENTIFIER ::= {
iso(1) member-body(2) US(840) rsadsi(113549) pkcs(1)
pkcs-3(3) 1
}
Here the context key gets generated jointly by the initiator and the target using the Diffie-Hellman key establishment algorithm ๐ฆ That means the target has to respond to the initiator for the key to be established, so this K-ALG can't be used with unilateral authentication in SPKM-2 (see Section 3.1) ๐ โโ๏ธ
2.4 One-Way Function (O-ALG) for Subkey Derivation Algorithm: ๐ง
Purpose:
so once you've set up a context key with the negotiated K-ALG, both the initiator and the target need to be able to derive a bunch of subkeys for the various C-ALGs and keyed I-ALGs running over the context ๐ธ Here's the vibe: number the agreed C-ALGs in their ordered list starting at "0" for the first one (the "default"), then "1", and so on. The I-ALG list gets numbered the exact same way ๐ The context key is a binary string of arbitrary length "M", and it has to follow this rule:
L <= M <= U
where the lower limit "L" is the bit length of the longest key needed by any agreed C-ALG or keyed I-ALG, and the upper limit "U" is the largest bit size that fits within the K-ALG parameters โจ
Examples:
Say DES and two-key-triple-DES are the negotiated confidentiality algorithms and DES-MAC is the negotiated keyed integrity algorithm (digital signatures don't use a context key, btw ๐). Then the context key must be at least 112 bits long ๐
If 512-bit RSAEncryption is the K-ALG in use, the originator can randomly generate a context key of any greater length up to 424 bits (the longest allowable RSA input specified in [PKCS-1]). The target figures out the length that was picked by removing the padding bytes during the RSA decryption operation ๐ง
On the other hand, if dhKeyAgreement is the K-ALG in use, the context key is the result of the Diffie-Hellman computation (except the high-order byte, which gets thrown away for security reasons ๐). So its length is the Diffie-Hellman modulus, p, minus 8 bits ๐
The derivation algorithm for a k-bit subkey goes like this:
rightmost_k_bits (OWF(context_key || x || n || s || context_key))
where:
- "x" is the ASCII character "C" (0x43) if the subkey is for a confidentiality algorithm, or the ASCII character "I" (0x49) if the subkey is for a keyed integrity algorithm;
- "n" is the number of the algorithm in the appropriate agreed list for the context (the ASCII character "0" (0x30), "1" (0x31), and so on);
- "s" is the "stage" of processing. It's always the ASCII character "0" (0x30), unless "k" is greater than the output size of OWF. In that case the OWF gets computed again and again with increasing ASCII values of "stage" (each OWF output gets concatenated onto the end of the previous ones) until "k" bits have been generated ๐;
- "||" is the concatenation operation; and
- "OWF" is any appropriate One-Way Function.
MD5 is the first O-ALG example:
MD5 OBJECT IDENTIFIER ::= {
iso(1) member-body(2) US(840) rsadsi(113549)
digestAlgorithm(2) 5
}
This algorithm is MANDATORY ๐
And SHA is the second one:
SHA OBJECT IDENTIFIER ::= {
iso(1) identified-organization(3) oiw(14) secsig(3)
algorithm(2) 18
}
Okay, real talk: existing hash functions might not satisfy all the required properties of OWFs ๐ญ That's exactly why the O-ALG OWF is negotiable during context establishment (see Section 2.5). That way, future improvements in OWF design can get slotted in easily ๐ฆ For example, in some environments a preferred OWF technique might be an encryption algorithm that encrypts the input specified above, using the context_key as the encryption key ๐ฅ
2.5 Negotiation: ๐ค
During context establishment in SPKM, the initiator offers a set of possible confidentiality algorithms and a set of possible integrity algorithms to the target. (Fun fact: the term "integrity algorithms" includes digital signature algorithms ๐ .) The target "selects" algorithms by sending back, in the same relative order, the subset of each offered list that it supports. Whatever the target picks becomes the usable set: the confidentiality ones are for C-ALG and the integrity ones are for I-ALG over the established context โจ Any C-ALG and I-ALG can be used for any message over the context, and the first confidentiality algorithm and the first integrity algorithm in the agreed sets become the default algorithms for that context ๐
The agreed confidentiality and integrity algorithms for a specific context define the valid values of the Quality of Protection (QOP) parameter used in the gss_getMIC() and gss_wrap() calls. See Section 5.2 for the full scoop ๐ If no response is expected from the target (unilateral authentication in SPKM-2), then the algorithms the initiator offered are the ones that can be used over the context. If that's unacceptable to the target, a delete token has to be sent to the initiator so the context never gets established ๐
โโ๏ธ
Also, in the first context establishment token, the initiator offers a set of possible K-ALGs, along with the key (or key half) for the first algorithm in the set (its preferred algorithm) ๐ If that K-ALG isn't acceptable to the target, the target has to choose one of the other K-ALGs in the set and send that choice back, along with the key (or key half) for the choice, in its response. Otherwise, a delete token must be sent so the context never gets established ๐ If it's needed (say the target picks a 2-pass K-ALG like dhKeyAgreement), the initiator will send its key half in a response to the target ๐ซถ
Finally, in the first context establishment token, the initiator offers a set of possible O-ALGs (just a single O-ALG if no response is expected). The single O-ALG the target chooses becomes the subkey derivation algorithm OWF used over the context ๐ง
In future versions of SPKM, other algorithms may be specified for any or all of I-ALG, C-ALG, K-ALG, and O-ALG ๐ธ
3. Token Formats ๐
This section is all about the protocol-visible characteristics of SPKM. It defines the elements of protocol for interoperability, and it's independent of language bindings per [RFC-1509] ๐
The SPKM GSS-API mechanism gets identified by an Object Identifier representing "SPKM-1" or "SPKM-2", with the values {spkm spkm-1(1)} or {spkm spkm-2(2)}. Here, spkm has the value {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) spkm(1)} โจ SPKM-1 uses random numbers for replay detection during context establishment, while SPKM-2 uses timestamps. (Heads up: for both mechanisms, sequence numbers are used to provide replay and out-of-sequence detection during the context, if the application asked for it ๐ฆ)
Tokens transferred between GSS-API peers (for security context management and per-message protection purposes) are defined ๐
3.1. Context Establishment Tokens โจ
okay bestie, this section has three classes of tokens ๐. "Initiator" tokens come out of gss_init_sec_context() and get consumed by gss_accept_sec_context(). "Target" tokens go the other way, coming out of gss_accept_sec_context() and getting consumed by gss_init_sec_context(). Then there are "Error" tokens, which either function can emit and either function can consume ๐ chaotic but it works ๐ซถ
so per RFC-1508, Appendix B, the very first context establishment token gets wrapped in framing like this ๐ง:
InitialContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE {
thisMech MechType,
-- MechType is OBJECT IDENTIFIER
-- representing "SPKM-1" or "SPKM-2"
innerContextToken ANY DEFINED BY thisMech
} -- contents mechanism-specific
when thisMech is SPKM-1 or SPKM-2, innerContextToken looks like this ๐:
SPKMInnerContextToken ::= CHOICE {
req [0] SPKM-REQ,
rep-ti [1] SPKM-REP-TI,
rep-it [2] SPKM-REP-IT,
error [3] SPKM-ERROR,
mic [4] SPKM-MIC,
wrap [5] SPKM-WRAP,
del [6] SPKM-DEL
}
this GSS-API framing shall be applied to every token the SPKM GSS-API mechanism emits, not just the initial token in a context establishment exchange ๐ญ that includes SPKM-REP-TI (the response from the Target to the Initiator), SPKM-REP-IT (the response from the Initiator to the Target), SPKM-ERROR, context-deletion tokens, and per-message tokens. RFC-1508 doesn't require it, but it lets implementations do enhanced error-checking, which is honestly so iconic ๐ฅ
the tag values from SPKMInnerContextToken ("[0]" through "[6]") give each token a token-id, and each token's tok-id field has similar info. it might look redundant, but they're doing different jobs ๐. the tag makes sure InitialContextToken can be decoded properly, and the tok-id makes sure, among other things, that the data tied to per-message tokens is cryptographically linked to the token type it's supposed to be. every innerContextToken also has a context-id field. see Section 6 for the whole story on token-id and context-id and how they get used in an SPKM support function).
the innerContextToken field of context establishment tokens for the SPKM GSS-API mechanism holds one of these messages: SPKM-REQ, SPKM-REP-TI, SPKM-REP-IT, or SPKM-ERROR. also, every innerContextToken is encoded in ASN.1 BER. to keep parsing simple, it's constrained to the DER subset defined in [X.509], clause 8.7 ๐ธ
the SPKM context establishment tokens are defined according to [X.509] Section 10 and are compatible with [9798] ๐ฆ. SPKM-1 (random numbers) uses Section 10.3, "Two-way Authentication", for unilateral authentication of the target to the initiator, and uses Section 10.4, "Three-way Authentication", when the initiator asks for mutual authentication. SPKM-2 (timestamps) uses Section 10.2, "One-way Authentication", for unilateral authentication of the initiator to the target, and uses Section 10.3, "Two-way Authentication", when mutual authentication is requested by the initiator.
ngl this next bit is where it gets spicy ๐ถ๏ธ for SPKM-2 unilateral authentication, no negotiation of K-ALG can happen. the target either accepts the K-ALG and context key the initiator gave it, or it rejects the context entirely. for SPKM-2 mutual or SPKM-1 unilateral authentication, there is some negotiation, but the target can only pick from the one-pass K-ALGs the initiator offered (or reject the context). the initiator can also ask the target to generate and transmit the context key instead ๐ง and for SPKM-1 mutual authentication, the target can pick any one-pass or two-pass K-ALG the initiator offered, and it can also be asked to generate and transmit the context key.
it's envisioned that typical use of SPKM-1 or SPKM-2 will involve mutual authentication ๐ unilateral authentication is available for both mechanisms, but its use is not generally recommended. main character energy is mutual auth, bestie ๐
3.1.1. Context Establishment Tokens - Initiator (first token) ๐
Okay so the initiator goes first ๐ To set up context, both sides might need the other side's public-key certificate(s) ๐. Sometimes the initiator just attaches the relevant ones to the first token. Other times it asks the target to send certificate data back in its response, or each side grabs what it needs on its own. Either way, the SPKM implementation has to be able to get certificates that match a supplied Name. How it actually does that is a local implementation thing, so it's outside the scope of this spec ๐
Here's the relevant SPKM-REQ syntax (imports from other documents are in Appendix A) โจ
SPKM-REQ ::= SEQUENCE {
requestToken REQ-TOKEN,
certif-data [0] CertificationData OPTIONAL,
auth-data [1] AuthorizationData OPTIONAL
-- see [RFC-1510] for a discussion of auth-data
}
CertificationData ::= SEQUENCE {
certificationPath [0] CertificationPath OPTIONAL,
certificateRevocationList [1] CertificateList OPTIONAL
} -- at least one of the above shall be present
CertificationPath ::= SEQUENCE {
userKeyId [0] OCTET STRING OPTIONAL,
-- identifier for user's public key
userCertif [1] Certificate OPTIONAL,
-- certificate containing user's public key
verifKeyId [2] OCTET STRING OPTIONAL,
-- identifier for user's public verification key
userVerifCertif [3] Certificate OPTIONAL,
-- certificate containing user's public verification key
theCACertificates [4] SEQUENCE OF CertificatePair OPTIONAL
} -- certification path from target to source
Having separate verification fields lets different key pairs (possibly for different algorithms) handle encryption/decryption and signing/verification ๐ฆ Presence of [0] or [1], with [2] and [3] absent, means the same key pair is used for enc/dec and verif/signing. (Fyi, this practice is not typically recommended ๐) Presence of [2] or [3] means a separate key pair is used for verif/signing, so [0] or [1] must also be present. Presence of [4] implies that at least one of [0], [1], [2], and [3] must also be present.
REQ-TOKEN ::= SEQUENCE {
req-contents Req-contents,
algId AlgorithmIdentifier,
req-integrity Integrity -- "token" is Req-contents
}
Integrity ::= BIT STRING
-- If corresponding algId specifies a signing algorithm,
-- "Integrity" holds the result of applying the signing procedure
-- specified in algId to the BER-encoded octet string which results
-- from applying the hashing procedure (also specified in algId) to
-- the DER-encoded octets of "token".
-- Alternatively, if corresponding algId specifies a MACing
-- algorithm, "Integrity" holds the result of applying the MACing
-- procedure specified in algId to the DER-encoded octets of
-- "token" (note that for MAC, algId must be one of the integrity
-- algorithms offered by the initiator with the appropriate subkey
-- derived from the context key (see Section 2.4) used as the key
-- input)
So the Integrity field for each of REQ-TOKEN, REP-TI-TOKEN, and REP-IT-TOKEN is expected to typically be a true digital signature ๐ That gives you unilateral or mutual authentication plus replay protection, as needed. BUT there are times when the MAC option is the right call ๐ For example, if the initiator wants to stay anonymous, then the first token (or the first and third tokens) get MACed and the second token gets signed. Another example is when a context that was already authenticated, established, and cached gets re-established later on. In that case, every exchanged token is MACed ๐ธ
The big win with MAC is less processing overhead ๐ง It's useful when authentication isn't required (like anonymity), or when authentication was already handled some other way (like being able to form the correct MAC on a "fresh" token during context re-establishment).
Req-contents ::= SEQUENCE {
tok-id INTEGER (256), -- shall contain 0100(hex)
context-id Random-Integer, -- see Section 6.3
pvno BIT STRING, -- protocol version number
timestamp UTCTime OPTIONAL, -- mandatory for SPKM-2
randSrc Random-Integer,
targ-name Name,
src-name [0] Name OPTIONAL,
-- must be supplied unless originator is "anonymous"
req-data Context-Data,
validity [1] Validity OPTIONAL,
-- validity interval for key (may be used in the
-- computation of security context lifetime)
key-estb-set Key-Estb-Algs,
-- specifies set of key establishment algorithms
key-estb-req BIT STRING OPTIONAL,
-- key estb. parameter corresponding to first K-ALG in set
-- (not used if initiator is unable or unwilling to
-- generate and securely transmit key material to target).
-- Established key must satisfy the key length constraints
-- specified in Section 2.4.
key-src-bind OCTET STRING OPTIONAL
-- Used to bind the source name to the symmetric key.
-- This field must be present for the case of SPKM-2
-- unilateral authen. if the K-ALG in use does not provide
-- such a binding (but is optional for all other cases).
-- The octet string holds the result of applying the
-- mandatory hashing procedure MD5 (in MANDATORY I-ALG;
-- see Section 2.1) as follows: MD5(src || context_key),
-- where "src" is the DER-encoded octets of src-name,
-- "context-key" is the symmetric key (i.e., the
-- unprotected version of what is transmitted in
-- key-estb-req), and "||" is the concatenation operation.
}
-- The protocol version number (pvno) parameter is a BIT STRING which
-- uses as many bits as necessary to specify all the SPKM protocol
-- versions supported by the initiator (one bit per protocol
-- version). The protocol specified by this document is version 0.
-- Bit 0 of pvno is therefore set if this version is supported;
-- similarly, bit 1 is set if version 1 (if defined in the future) is
-- supported, and so on. Note that for unilateral authentication
-- using SPKM-2, no response token is expected during context
-- establishment, so no protocol negotiation can take place; in this
-- case, the initiator must set exactly one bit of pvno. The version
-- of REQ-TOKEN must correspond to the highest bit set in pvno.
-- The "validity" parameter above is the only way within SPKM for
-- the initiator to transmit desired context lifetime to the target.
-- Since it cannot be guaranteed that the initiator and target have
-- synchronized time, the span of time specified by "validity" is to
-- be taken as definitive (rather than the actual times given in this
-- parameter).
Random-Integer ::= BIT STRING
-- Each SPKM implementation is responsible for generating a "fresh"
-- random number for the purpose of context establishment; that is,
-- one which (with high probability) has not been used previously.
-- There are no cryptographic requirements on this random number
-- (i.e., it need not be unpredictable, it simply needs to be fresh).
Okay the pvno bit string is giving protocol version roster ๐ Each bit is one SPKM version the initiator supports. Version 0 is the one this doc defines, so bit 0 gets set if it's supported, bit 1 for version 1 (if it ever gets defined), and so on. For unilateral authentication with SPKM-2, there's no response token during context establishment, so there's no negotiation happening. In that case the initiator must set exactly one bit of pvno, and the version of REQ-TOKEN must match the highest bit set in pvno ๐
The validity parameter is the only way within SPKM for the initiator to tell the target how long it wants the context to last โณ Since nobody can guarantee the two sides have synced clocks, the span of time in validity is the definitive one, not the literal times in that parameter ๐ฐ๏ธ
The random number for each context establishment has to be "fresh" ๐ฒ That just means the implementation makes sure it probably hasn't been used before. There are no cryptographic requirements on it. It doesn't need to be unpredictable, it just needs to be fresh ๐
Context-Data ::= SEQUENCE {
channelId ChannelId OPTIONAL, -- channel bindings
seq-number INTEGER OPTIONAL, -- sequence number
options Options,
conf-alg Conf-Algs, -- confidentiality. algs.
intg-alg Intg-Algs, -- integrity algorithm
owf-alg OWF-Algs -- for subkey derivation
}
ChannelId ::= OCTET STRING
Options ::= BIT STRING {
delegation-state (0),
mutual-state (1),
replay-det-state (2), -- used for replay det. during context
sequence-state (3), -- used for sequencing during context
conf-avail (4),
integ-avail (5),
target-certif-data-required (6)
-- used to request targ's certif. data
}
Conf-Algs ::= CHOICE {
algs [0] SEQUENCE OF AlgorithmIdentifier,
null [1] NULL
-- used when conf. is not available over context
} -- for C-ALG (see Section 5.2 for discussion of QOP)
Intg-Algs ::= SEQUENCE OF AlgorithmIdentifier
-- for I-ALG (see Section 5.2 for discussion of QOP)
OWF-Algs ::= SEQUENCE OF AlgorithmIdentifier
-- Contains exactly one algorithm in REQ-TOKEN for SPKM-2
-- unilateral, and contains at least one algorithm otherwise.
-- Always contains exactly one algorithm in REP-TOKEN.
Key-Estb-Algs ::= SEQUENCE OF AlgorithmIdentifier
-- to allow negotiation of K-ALG
Now the authentication flow ๐ A context establishment based on SPKM does unilateral authentication if the mutual-req bit isn't set in the application's call to gss_init_sec_context(). SPKM-2 does this with only SPKM-REQ, which authenticates the initiator to the target. SPKM-1 does it with both SPKM-REQ and SPKM-REP-TI, which authenticates the target to the initiator.
Apps that need both peers authenticated (initiator and target) have to request mutual authentication, which sets "mutual-state" in the SPKM-REQ Options ๐ค When that happens, the context target replies to the initiator with an SPKM-REP-TI token. If SPKM-2 was chosen, that finishes the (timestamp-based) mutual authentication exchange. If SPKM-1 was chosen and SPKM-REP-TI gets sent, the initiator replies to the target with an SPKM-REP-IT token, which finishes the (random-number-based) mutual authentication exchange ๐
The other bits in the Options field of Context-Data are explained in RFC-1508 โจ The one exception is target-certif-data-required. The initiator sets it to TRUE to ask the target to send its certification data back in the SPKM-REP-TI token. For unilateral authentication in SPKM-2 (where no SPKM-REP-TI token gets built), both the initiator and target just ignore this option bit ๐
Okay that's the whole first token, bestie ๐ซถ Next up, the rest of the exchange! ๐ฆ
3.1.2. Context Establishment Tokens - Target โจ
SPKM-REP-TI ::= SEQUENCE {
responseToken REP-TI-TOKEN,
certif-data CertificationData OPTIONAL
-- included if target-certif-data-required option was
-- set to TRUE in SPKM-REQ
}
REP-TI-TOKEN ::= SEQUENCE {
rep-ti-contents Rep-ti-contents,
algId AlgorithmIdentifier,
rep-ti-integ Integrity -- "token" is Rep-ti-contents
}
Rep-ti-contents ::= SEQUENCE {
tok-id INTEGER (512), -- shall contain 0200 (hex)
context-id Random-Integer, -- see Section 6.3
pvno [0] BIT STRING OPTIONAL, -- prot. version number
timestamp UTCTime OPTIONAL, -- mandatory for SPKM-2
randTarg Random-Integer,
src-name [1] Name OPTIONAL,
-- must contain whatever value was supplied in REQ-TOKEN
targ-name Name,
randSrc Random-Integer,
rep-data Context-Data,
validity [2] Validity OPTIONAL,
-- validity interval for key (used if the target can only
-- support a shorter context lifetime than was offered in
-- REQ-TOKEN)
key-estb-id AlgorithmIdentifier OPTIONAL,
-- used if target is changing key estb. algorithm (must be
-- a member of initiators key-estb-set)
key-estb-str BIT STRING OPTIONAL
-- contains (1) the response to the initiators
-- key-estb-req (if init. used a 2-pass K-ALG), or (2) the
-- key-estb-req corresponding to the K-ALG supplied in
-- above key-estb-id, or (3) the key-estb-req corresponding
-- to the first K-ALG supplied in initiator's key-estb-id,
-- if initiator's (OPTIONAL) key-estb-req was not used
-- (target's key-estb-str must be present in this case).
-- Established key must satisfy the key length constraints
-- specified in Section 2.4.
}
Okay bestie, so the target's reply token is basically the big "yes, let's do this" ๐ It's wrapped up in a REP-TI-TOKEN, and the contents are tucked inside Rep-ti-contents. There's a tok-id that has to be 0200 in hex ๐ and a context-id, randTarg, randSrc, and all the names. Some fields are optional, like pvno, timestamp, validity, and the key-establishment stuff. The validity one is for when the target can only handle a shorter context lifetime than the initiator offered ๐ฐ๏ธ And key-estb-str is the spicy one ๐ถ๏ธ It can hold the response to the initiator's request, or a request for a different K-ALG, and if the initiator skipped its optional request, the target has to fill this one in. The established key has to follow the key length rules from Section 2.4. Obsessed with how many branches this has, ngl ๐
The protocol version number (pvno) is a BIT STRING that uses as many bits as it needs to name a single SPKM protocol version. That version has to be one the initiator offered AND the target actually supports, with one bit per version ๐ฆ So the target sets exactly one bit, never more. If the target supports none of the versions the initiator offered, a delete token must be returned so the context is never established. Literally the most dramatic "nope" ๐
If the initiator's pvno has only one bit set and the target happens to support that version, then that version gets used over the context, and the pvno parameter of REP-TOKEN can be left out. Simple. Then there's the plot twist ๐ฟ If the two sides share one or more versions, but the version on the REQ-TOKEN they got isn't supported by the target, a REP-TOKEN has to be sent with a desired version bit set in pvno, and dummy values go in every field after it. The initiator can then send a brand new REQ-TOKEN with the right version, which basically restarts context establishment from scratch. Restart arc unlocked ๐โจ
3.1.3. Context Establishment Tokens - Initiator (second token) ๐ธ
Here's the relevant SPKM-REP-IT syntax, bestie ๐ซถ
SPKM-REP-IT ::= SEQUENCE {
responseToken REP-IT-TOKEN,
algId AlgorithmIdentifier,
rep-it-integ Integrity -- "token" is REP-IT-TOKEN
}
REP-IT-TOKEN ::= SEQUENCE {
tok-id INTEGER (768), -- shall contain 0300 (hex)
context-id Random-Integer,
randSrc Random-Integer,
randTarg Random-Integer,
targ-name Name, -- the targ-name specified in REP-TI
src-name Name OPTIONAL,
-- must contain whatever value was supplied in REQ-TOKEN
key-estb-rep BIT STRING OPTIONAL
-- contains the response to targets key-estb-str
-- (if target selected a 2-pass K-ALG)
}
This is the initiator's second token, the one that answers the target. It has the 0300 tok-id, the context and random values, the target name copied from REP-TI, and the source name, which has to match whatever was in REQ-TOKEN. The key-estb-rep field is only there if the target picked a 2-pass K-ALG, and then it carries the response to the target's key-estb-str ๐
3.1.4. Error Token ๐จ
The syntax of SPKM-ERROR is as follows:
SPKM-ERROR ::= SEQUENCE {
error-token ERROR-TOKEN,
algId AlgorithmIdentifier,
integrity Integrity -- "token" is ERROR-TOKEN
}
ERROR-TOKRN ::= SEQUENCE {
tok-id INTEGER (1024), -- shall contain 0400 (hex)
context-id Random-Integer
}
The SPKM-ERROR token is only used during context establishment, so it's strictly a setup-phase thing ๐ง If an SPKM-REQ or SPKM-REP-TI token arrives in error, the receiving function (either gss_init_sec_context() or gss_accept_sec_context()) generates an SPKM-ERROR token to send to the peer, but only if the peer is still in context establishment. The function then returns GSS_S_CONTINUE_NEEDED.
If, on the other hand, the peer isn't expecting any context establishment response because it already finished, things go differently ๐ญ The function returns the appropriate major status code (for example GSS_S_BAD_SIG) along with a minor status of GSS_SPKM_S_SG_CONTEXT_ESTB_ABORT, and all the context-relevant information gets deleted. The output token won't be an SPKM-ERROR token. It'll be an SPKM-DEL token, which the peer's gss_process_context_token() will process.
If gss_init_sec_context() receives an error token, whether valid or invalid, it regenerates SPKM-REQ as its output token and returns GSS_S_CONTINUE_NEEDED. (Side note: if the peer's gss_accept_sec_context() gets an SPKM-REQ token while it's expecting an SPKM-REP-IT token, it ignores the SPKM-REQ and returns a zero-length output token with a major status of GSS_S_CONTINUE_NEEDED.)
Similarly, if gss_accept_sec_context() receives an error token, whether valid or invalid, it regenerates SPKM-REP-TI as its output token and returns GSS_S_CONTINUE_NEEDED.
md5WithRsa is the one currently stipulated for signing context establishment tokens ๐ If the two sides disagree about modulus bitlength, you can sort it out with the SPKM-ERROR token. The context initiator signs REQ-TOKEN using the strongest RSA it supports (for example 1024 bits). If the target can't verify signatures of that length, it sends SPKM-ERROR signed with the strongest RSA that it does support (for example 512).
By the end of this exchange, both sides know what RSA bitlength the other one supports, because the size of the signature equals the size of the modulus. Exchanges can keep going with successively smaller supported bitlengths until they either agree on one or context establishment gets aborted because no agreement is possible. Negotiation arc, but make it cryptographic ๐
3.2. Per-Message and Context Deletion Tokens ๐
Three classes of tokens are defined in this section. "MIC" tokens are emitted by calls to gss_getMIC() and consumed by calls to gss_verifyMIC(). "Wrap" tokens are emitted by calls to gss_wrap() and consumed by calls to gss_unwrap(). Then there are context deletion tokens, which are emitted by calls to gss_init_sec_context(), gss_accept_sec_context(), or gss_delete_sec_context() and consumed by calls to gss_process_context_token(). Three types, three vibes ๐ฆ
3.2.1. Per-message Tokens - Sign / MIC ๐
Using the gss_sign() / gss_getMIC() call gives you a token that's separate from the user data it protects, and you can use that token to verify the integrity of the data as it was received. The sending application can send the token and the data separately, and it's the receiving application's job to link the received data with the received token ๐งฉ
The SPKM-MIC token has the following format:
SPKM-MIC ::= SEQUENCE {
mic-header Mic-Header,
int-cksum BIT STRING
-- Checksum over header and data,
-- calculated according to algorithm
-- specified in int-alg field.
}
Mic-Header ::= SEQUENCE {
tok-id INTEGER (257),
-- shall contain 0101 (hex)
context-id Random-Integer,
int-alg [0] AlgorithmIdentifier OPTIONAL,
-- Integrity algorithm indicator (must
-- be one of the agreed integrity
-- algorithms for this context).
-- field not present = default id.
snd-seq [1] SeqNum OPTIONAL -- sequence number field.
}
SeqNum ::= SEQUENCE {
num INTEGER, -- the sequence number itself
dir-ind BOOLEAN -- a direction indicator
}
3.2.1.1. Checksum ๐ง
Here's the checksum procedure, and it's common to all algorithms. Quick note, bestie: for SPKM, "checksum" covers digital signatures as well as hashes and MACs ๐ซง Checksums get calculated over the data field, logically prepended by the bytes of the plaintext token header (mic-header). That binds the data to the entire plaintext header, which helps minimize the chance of malicious splicing. Sneaky attackers, denied ๐ โโ๏ธ
For example, if int-alg specifies the md5WithRSA algorithm, the checksum is formed by computing an MD5 [RFC-1321] hash over the plaintext data (prepended by the header), and then computing an RSA signature [PKCS1] on the 16-byte MD5 result. The signature is computed using the RSA private key retrieved from the credentials structure. The result, whose length is implied by the "modulus" parameter in the private key, gets stored in the int-cksum field.
If int-alg specifies a keyed hashing algorithm (for example DES-MAC or md5-DES-CBC), the key to use is the appropriate subkey derived from the context key (see Section 2.4). Again, the result, whose length is implied by int-alg, gets stored in the int-cksum field ๐
3.2.1.2. Sequence Number ๐ข
It's assumed that the underlying transport layers (of whatever protocol stack the application is using) will provide adequate communications reliability. That means non-malicious loss, re-ordering, and so on of data packets will be handled correctly. So sequence numbers are used in SPKM purely for security reasons, not reliability ones. Their job is to avoid malicious loss, replay, or re-ordering of SPKM tokens. That's why it's recommended that applications request sequencing and replay detection over all contexts ๐ก๏ธ Sequence numbers also mean there's no requirement for secure timestamps in the message tokens, which is such a relief ๐
The initiator's initial sequence number for the current context may be explicitly given in the Context-Data field of SPKM-REQ. The target's initial sequence number may be explicitly given in the Context-Data field of SPKM-REP-TI. If either of these isn't given, the default value of 00 is used.
The sequence number field is formed from the sender's four-byte sequence number and a Boolean direction-indicator. FALSE means the sender is the context initiator, and TRUE means the sender is the context acceptor. After constructing a gss_sign()/getMIC() or gss_seal()/wrap() token, the sender's seq. number goes up by 1 โญ
3.2.1.3. Sequence Number Processing ๐ฆ
okay so the receiver checks two things: the sequence number against the one it's expecting, AND the direction indicator against the expected direction indicator ๐. Here's how each outcome plays out:
- If the sequence number in the token is higher than the expected number, the expected sequence number gets bumped up and
GSS_S_GAP_TOKENis returned ๐. - If the token sequence number is lower than the expected number, the expected sequence number stays put, and
GSS_S_DUPLICATE_TOKEN,GSS_S_UNSEQ_TOKEN, orGSS_S_OLD_TOKENgets returned, whichever one fits ๐ซ . - If the direction indicator is wrong, the expected sequence number stays put too, and
GSS_S_UNSEQ_TOKENis returned ๐ โโ๏ธ.
Now the slay part ๐ โจ. The sequence number is used as part of the input to the integrity checksum, so it doesn't need to be encrypted. And if someone tries to splice a checksum and a sequence number from different messages together, it gets caught ๐ต๏ธโโ๏ธ. The direction indicator is what catches tokens that have been maliciously reflected back at you ๐ช. Iconic protection, honestly ๐ฅ.
3.2.2. Per-message Tokens - Seal / Wrap ๐
Calling gss_seal() / gss_wrap() gives you a token that wraps up the input user data (optionally encrypted) together with its integrity check bits ๐. The token has an integrity header first, then a body that holds either the plaintext data (if conf-alg = NULL) or encrypted data (using the right subkey from Section 2.4 for one of the agreed C-ALGs for this context) ๐.
The SPKM-WRAP token looks like this ๐:
SPKM-WRAP ::= SEQUENCE {
wrap-header Wrap-Header,
wrap-body Wrap-Body
}
Wrap-Header ::= SEQUENCE {
tok-id INTEGER (513),
-- shall contain 0201 (hex)
context-id Random-Integer,
int-alg [0] AlgorithmIdentifier OPTIONAL,
-- Integrity algorithm indicator (must
-- be one of the agreed integrity
-- algorithms for this context).
-- field not present = default id.
conf-alg [1] Conf-Alg OPTIONAL,
-- Confidentiality algorithm indicator
-- (must be NULL or one of the agreed
-- confidentiality algorithms for this
-- context).
-- field not present = default id.
-- NULL = none (no conf. applied).
snd-seq [2] SeqNum OPTIONAL
-- sequence number field.
}
Wrap-Body ::= SEQUENCE {
int-cksum BIT STRING,
-- Checksum of header and data,
-- calculated according to algorithm
-- specified in int-alg field.
data BIT STRING
-- encrypted or plaintext data.
}
Conf-Alg ::= CHOICE {
algId [0] AlgorithmIdentifier,
null [1] NULL
}
3.2.2.1: Confounding ๐
Same as in [KRB5], an 8-byte random confounder gets stuck onto the front of the data ๐ง. Why? To make up for the fact that an IV of zero is used for encryption. The result is called the "confounded" data field ๐ซถ.
3.2.2.2. Checksum ๐
Here's the checksum calculation procedure, which is shared by all the algorithms ๐งฎ. Checksums are calculated over the plaintext data field, with the bytes of the plaintext token header (wrap-header) logically prepended to it. Just like gss_sign() / gss_getMIC(), this binds the data to the entire plaintext header, which helps minimize the chances of malicious splicing ๐ก๏ธ.
The examples for md5WithRSA and DES-MAC are exactly as specified in 3.2.1.1 ๐.
Now for the spicy combo. If int-alg says md5-DES-CBC and conf-alg says anything other than DES-CBC, the checksum is computed according to 3.2.1.1 and the result goes into int-cksum ๐ธ. But if conf-alg says DES-CBC, the encryption and the integrity happen like this ๐:
- An MD5 [RFC-1321] hash gets computed over the plaintext data (with the header prepended).
- This 16-byte value gets appended to the concatenation of the "confounded" data and 1-8 padding bytes (the padding is as specified in [KRB5] for DES-CBC).
- The result is then CBC encrypted using the DES-CBC subkey (see Section 2.4) and placed in the "data" field of Wrap-Body.
- The final two blocks of ciphertext (i.e., the encrypted MD5 hash) are also placed in the
int-cksumfield of Wrap-Body as the integrity checksum ๐.
Next up, if int-alg says sum64-DES-CBC, then conf-alg must say DES-CBC (i.e., confidentiality must be requested by the calling application or SPKM will return an error) ๐จ. Encryption and integrity happen together in a single pass using the DES-CBC subkey ๐งต:
- The sum (modulo 2**64 - 1) of all the plaintext data blocks (with the header prepended) is computed.
- This 8-byte value gets appended to the concatenation of the "confounded" data and 1-8 padding bytes (the padding is as specified in [KRB5] for DES-CBC).
- As above, the result is then CBC encrypted and placed in the "data" field of Wrap-Body.
- The final block of ciphertext (i.e., the encrypted sum) is also placed in the
int-cksumfield of Wrap-Body as the integrity checksum โจ.
3.2.2.3 Sequence Number ๐ข
Sequence numbers get computed and processed for gss_wrap() exactly as specified in 3.2.1.2 and 3.2.1.3 ๐.
3.2.2.4: Data Encryption ๐
This procedure is followed unless one of these is true ๐
โโ๏ธ: (a) conf-alg is NULL (no encryption), (b) conf-alg is DES-CBC and int-alg is md5-DES-CBC (encryption as specified in 3.2.2.2), or (c) int-alg is sum64-DES-CBC (encryption as specified in 3.2.2.2).
Otherwise, the "confounded" data gets padded and encrypted according to the algorithm named in the conf-alg field ๐ท. The data is encrypted using CBC with an IV of zero. The key is the right subkey, derived from the established context key using the subkey derivation algorithm described in Section 2.4. This is what makes sure the subkey used for encryption and the subkey used for a separate, keyed integrity algorithm (for example DES-MAC, but not sum64-DES-CBC) are different ๐ฆ.
3.2.3. Context deletion token ๐๏ธ
The token from gss_delete_sec_context() is based on the format of tokens from gss_sign() / gss_getMIC() ๐งพ.
The SPKM-DEL token looks like this:
SPKM-DEL ::= SEQUENCE {
del-header Del-Header,
int-cksum BIT STRING
-- Checksum of header, calculated
-- according to algorithm specified
-- in int-alg field.
}
Del-Header ::= SEQUENCE {
tok-id INTEGER (769),
-- shall contain 0301 (hex)
context-id Random-Integer,
int-alg [0] AlgorithmIdentifier OPTIONAL,
-- Integrity algorithm indicator (must
-- be one of the agreed integrity
-- algorithms for this context).
-- field not present = default id.
snd-seq [1] SeqNum OPTIONAL
-- sequence number field.
}
The snd-seq field gets calculated just like it does for tokens from gss_sign() / gss_getMIC(). The int-cksum field also gets calculated like that, except the user-data part of the checksum data is a zero-length string ๐ซง.
If a valid delete token comes in, the SPKM implementation deletes the context, and gss_process_context_token() returns a major status of GSS_S_COMPLETE and a minor status of GSS_SPKM_S_SG_CONTEXT_DELETED ๐. But if the delete token is invalid, the context does NOT get deleted, and gss_process_context_token() returns the appropriate major status (GSS_S_BAD_SIG, for example) and a minor status of GSS_SPKM_S_SG_BAD_DELETE_TOKEN_RECD ๐ฌ. At that point the application might want to check the context status, for example by sending a sealed/wrapped test message to its peer and waiting for a sealed/wrapped response ๐งช.
4. Name Types and Object Identifiers ๐ท๏ธ
No mandatory name forms have been defined for SPKM just yet. This section is for further study ๐ญ.
4.1. Optional Name Forms โจ
This section talks about name forms that implementations of the SPKM GSS-API mechanism can optionally support ๐ . It's recognized that OS-specific functions outside GSS-API are likely to exist for translating between these forms, and that GSS-API implementations supporting these forms may be layered on top of those OS-specific functions ๐งฉ. Including this support inside GSS-API implementations is meant as a convenience for applications ๐.
4.1.1. User Name Form ๐ค
This name form is represented by the Object Identifier {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) generic(1) user_name(1)}. The recommended symbolic name for this type is "GSS_SPKM_NT_USER_NAME" ๐.
This name type is used to indicate a named user on a local system. Its interpretation is OS-specific. This name form is built like this:
username
4.1.2. Machine UID Form ๐ค
This name form is represented by the Object Identifier {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. The recommended symbolic name for this type is "GSS_SPKM_NT_MACHINE_UID_NAME" ๐.
This name type is used to indicate a numeric user identifier that corresponds to a user on a local system. Its interpretation is OS-specific. The gss_buffer_desc representing a name of this type ought to contain a locally-significant uid_t, represented in host byte order ๐ข. The gss_import_name() operation resolves this uid into a username, which is then treated as the User Name Form ๐ช.
4.1.3. String UID Form ๐งต
This name form is represented by the Object Identifier {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) generic(1) string_uid_name(3)}. The recommended symbolic name for this type is "GSS_SPKM_NT_STRING_UID_NAME" ๐.
This name type is used to indicate a string of digits representing the numeric user identifier of a user on a local system. Its interpretation is OS-specific. This name type is similar to the Machine UID Form, except that the buffer contains a string representing the uid_t ๐ซถ.
5. Parameter Definitions ๐ง
This section defines the parameter values used by the SPKM GSS-API mechanism ๐. It defines interface elements to support portability ๐ธ.
5.1. Minor Status Codes โจ
okay bestie, this part is all about minor_status codes! ๐ The spec recommends a set of common symbolic names for the minor_status values that the SPKM GSS-API mechanism returns, and that's lowkey huge for portability ๐ฆ because independent implementors can all use the same names. Also, gss_display_status() lets callers turn minor_status numbers into text, so nobody has to squint at raw numbers ๐
Every implementation must make available a facility (through include files or other means) that translates these symbolic names into the concrete values that a particular GSS-API implementation uses for the minor_status values in this section ๐ง It's recognized that this list may grow over time, and that implementation-specific minor_status codes may be needed too ๐
5.1.1. Non-SPKM-specific codes (Minor Status Code MSB, bit 31, SET) ๐
5.1.1.1. GSS-Related codes (Minor Status Code bit 30 SET) ๐
GSS_S_G_VALIDATE_FAILED
/* "Validation error" */
GSS_S_G_BUFFER_ALLOC
/* "Couldn't allocate gss_buffer_t data" */
GSS_S_G_BAD_MSG_CTX
/* "Message context invalid" */
GSS_S_G_WRONG_SIZE
/* "Buffer is the wrong size" */
GSS_S_G_BAD_USAGE
/* "Credential usage type is unknown" */
GSS_S_G_UNAVAIL_QOP
/* "Unavailable quality of protection specified" */
5.1.1.2. Implementation-Related codes (Minor Status Code bit 30 OFF) ๐ง
GSS_S_G_MEMORY_ALLOC
/* "Couldn't perform requested memory allocation" */
5.1.2. SPKM-specific-codes (Minor Status Code MSB, bit 31, OFF) ๐ฆ
GSS_SPKM_S_SG_CONTEXT_ESTABLISHED
/* "Context is already fully established" */
GSS_SPKM_S_SG_BAD_INT_ALG_TYPE
/* "Unknown integrity algorithm type in token" */
GSS_SPKM_S_SG_BAD_CONF_ALG_TYPE
/* "Unknown confidentiality algorithm type in token" */
GSS_SPKM_S_SG_BAD_KEY_ESTB_ALG_TYPE
/* "Unknown key establishment algorithm type in token" */
GSS_SPKM_S_SG_CTX_INCOMPLETE
/* "Attempt to use incomplete security context" */
GSS_SPKM_S_SG_BAD_INT_ALG_SET
/* "No integrity algorithm in common from offered set" */
GSS_SPKM_S_SG_BAD_CONF_ALG_SET
/* "No confidentiality algorithm in common from offered set" */
GSS_SPKM_S_SG_BAD_KEY_ESTB_ALG_SET
/* "No key establishment algorithm in common from offered set" */
GSS_SPKM_S_SG_NO_PVNO_IN_COMMON
/* "No protocol version number in common from offered set" */
GSS_SPKM_S_SG_INVALID_TOKEN_DATA
/* "Data is improperly formatted: cannot encode into token" */
GSS_SPKM_S_SG_INVALID_TOKEN_FORMAT
/* "Received token is improperly formatted: cannot decode" */
GSS_SPKM_S_SG_CONTEXT_DELETED
/* "Context deleted at peer's request" */
GSS_SPKM_S_SG_BAD_DELETE_TOKEN_RECD
/* "Invalid delete token received -- context not deleted" */
GSS_SPKM_S_SG_CONTEXT_ESTB_ABORT
/* "Unrecoverable context establishment error. Context deleted" */
5.2. Quality of Protection Values ๐
okay so the Quality of Protection (QOP) parameter is how the SPKM GSS-API mechanism picks between different confidentiality and integrity-checking algorithms ๐
It's an input to gss_sign() and gss_seal() (also known as gss_getMIC() and gss_wrap()). Once both sides have agreed on these sets of algorithms, QOP just selects from those ordered sets. Simple, but so important โจ
Here's how the agreement goes ๐ซถ The SPKM-REQ token carries an ordered sequence of Alg. IDs for the integrity-checking algorithms the initiator supports, and another ordered sequence of Alg. IDs for the confidentiality algorithms the initiator supports. The target sends back the subset of each list that it also supports, inside the SPKM-REP-TI token, keeping the same relative order the initiator used. So the initiator and target each know what they support themselves, plus what both sides support (and that second list is what counts as "supported over the established context") ๐ฆ That's where QOP gets its meaning. For example, an application might request integrity algorithm number 3 as defined by the mechanism specification. If that algorithm is supported over this context, it gets used. If not, you get GSS_S_FAILURE plus an appropriate minor status code ๐
If the SPKM-REP-TI token isn't used (unilateral authentication using SPKM-2), then the "agreed" sets of Alg. IDs are simply taken to be the initiator's sets. If that's unacceptable to the target, the target must return an error token so the context is never established ๐ญ Also, for the sake of interoperability, the initiator isn't required to offer every algorithm it supports. It can offer just the mandated or recommended SPKM algorithms, since those are the ones the target is likely to support ๐ธ
The QOP parameter for SPKM is a 32-bit unsigned integer (an OM_uint32) with the bit-field assignments below. Confidentiality lives in the upper half and Integrity in the lower half, so take a peek at the diagram ๐
Confidentiality Integrity
31 (MSB) 16 15 (LSB) 0
------------------------------------|-----------------------------------
| TS (5) | U(3) | IA (4) | MA (4) | TS (5) | U(3) | IA (4) | MA(4) |
------------------------------------|-----------------------------------
Okay so where the table stops, the bits get their jobs, bestie ๐
- TS is a 5-bit Type Specifier (a semantic qualifier whose value specifies the type of algorithm which may be used to protect the corresponding token -- see below for details) ๐
- U is a 3-bit Unspecified field (available for future use/expansion) ๐ธ
- IA is a 4-bit field enumerating Implementation-specific Algorithms ๐ง
- MA is a 4-bit field enumerating Mechanism-defined Algorithms ๐
Now the QOP parameter is read in a specific order, and the same procedure is used for both the confidentiality and the integrity halves ๐ฆ The MA field gets checked first. If it is non-zero, then the algorithm protecting the token is the mechanism-specified algorithm for that integer value โจ
If MA is zero, then IA is checked next. If that value is non-zero, the algorithm protecting the token is the implementation-specified algorithm for that integer value, but only if that algorithm is available over the established context ๐ซถ ngl this one can be a little messy, because a particular value might mean one algorithm in one implementation of the mechanism, not be supported at all, or mean a completely different algorithm in another implementation. So using this field may hinder portability ๐
Last stop: if both MA and IA are zero, then TS gets checked. A TS value of zero means the default algorithm for the established context. That default is the first algorithm on the initiator's list of offered algorithms (confidentiality or integrity, depending on which half of QOP is being looked at) that is supported over the context ๐ A non-zero TS value points to a particular algorithm qualifier, and picks the first algorithm supported over the context that satisfies that qualifier ๐ฅ
These TS values (aka algorithm qualifiers) are specified, and other values may be added in the future ๐
For the Confidentiality TS field:
00001 (1) = SPKM_SYM_ALG_STRENGTH_STRONG
00010 (2) = SPKM_SYM_ALG_STRENGTH_MEDIUM
00011 (3) = SPKM_SYM_ALG_STRENGTH_WEAK
For the Integrity TS field:
00001 (1) = SPKM_INT_ALG_NON_REP_SUPPORT
00010 (2) = SPKM_INT_ALG_REPUDIABLE
Okay, the "strong, medium, and weak" labels are honestly debatable, and they'll probably change over time ๐ญ For this version, though, here's how they're defined. A confidentiality algorithm is "weak" if its effective key length is 40 bits or less. It's "medium-strength" if the effective key length is strictly between 40 and 80 bits. And it's "strong" if the effective key length is 80 bits or greater. (Quick note: "effective key length" describes the computational effort needed to break a cipher using the best-known cryptanalytic attack against that cipher ๐ง )
A five-bit TS field can hold up to 31 qualifiers for each of confidentiality and integrity, since "0" is reserved for "default" ๐ This document only specifies three for confidentiality and two for integrity, which leaves a lot of room for future specs ๐ฆ People have suggested qualifiers like "fast", "medium-speed", and "slow", but those are hard to quantify, and they depend on the platform and processor anyway. So they got left out of this first spec ๐ The goal is for TS terms to be quantitative, environment-independent qualifiers of algorithms, as much as that's possible โจ
The QOP structure is meant to work like this ๐
- TS values are specified at the GSS-API level, so they're portable across mechanisms. Apps that know nothing about algorithms can still pick the "quality" of protection for their message tokens ๐
- MA values are specified at the mechanism level, so they're portable across implementations of a mechanism. For example, every implementation of the Kerberos V5 GSS mechanism must support these:
GSS_KRB5_INTEG_C_QOP_MD5 (value: 1)
GSS_KRB5_INTEG_C_QOP_DES_MD5 (value: 2)
GSS_KRB5_INTEG_C_QOP_DES_MAC (value: 3)
(Note that these Kerberos-specified integrity QOP values do not conflict with the QOP structure defined above ๐ซถ)
- IA values are specified at the implementation level (in user documentation, for example), so they're typically non-portable ๐ง An app that knows its own mechanism implementation and its peer's mechanism implementation, however, is free to use these values, since they'll be perfectly valid and meaningful over that context and between those peers ๐
The receiver of a token must pass back to its calling application a QOP parameter with all relevant fields set. For example, if triple-DES has been specified by a mechanism as algorithm 8, then a receiver of a triple-DES-protected token must pass to its application (QOP Confidentiality TS=1, IA=0, MA=8). That way, the app is free to read whichever part of the QOP it understands, either TS or IA/MA ๐
Here's a stipulation to help with implementation and interoperability โจ The set of integrity Alg. IDs sent by the initiator must contain at least one that specifies an algorithm which computes a digital signature supporting non-repudiation, and must contain at least one that specifies any other (repudiable) integrity algorithm. The subset of integrity Alg. IDs returned by the target must also contain at least one that specifies an algorithm which computes a digital signature supporting non-repudiation, plus at least one that specifies a repudiable integrity algorithm ๐ฅ
The reason for this is to make sure every SPKM implementation provides an integrity service that supports non-repudiation, and one that doesn't ๐ธ An app that has no idea about the underlying algorithms can choose one or the other by passing (QOP Integrity TS=1, IA=MA=0) or (QOP Integrity TS=2, IA=MA=0). And even though an initiator who wants to stay anonymous will never actually use the non-repudiable digital signature, that integrity service still has to be available over the context so the target can use it if it wants ๐ฅน
Finally, following the MANDATORY and RECOMMENDED algorithms given in Section 2, these QOP values are specified for SPKM ๐
For the Confidentiality MA field:
0001 (1) = DES-CBC
For the Integrity MA field:
0001 (1) = md5WithRSA
0010 (2) = DES-MAC
6. Support Functions โจ
This section describes a mandatory support function for SPKM-conformant implementations, which may actually be valuable in all GSS-API mechanisms ๐ง It uses the token-id and context-id info included in SPKM context-establishment, error, context-deletion, and per-message tokens. The function is defined in the next section ๐
6.1. SPKM_Parse_token call
Inputs:
input_token OCTET STRING
Outputs:
major_status INTEGER,minor_status INTEGER,mech_type OBJECT IDENTIFIER,token_type INTEGER,context_handle CONTEXT HANDLE,
Return major_status codes:
GSS_S_COMPLETEmeans the input_token could be parsed for all relevant fields. The results are stored in mech_type, token_type and context_handle, respectively (with NULLs in any parameters that aren't relevant) ๐ฆGSS_S_DEFECTIVE_TOKENmeans either the token-id or the context-id (if it was expected) info couldn't be parsed. A non-NULL return value in token_type means the latter situation happened ๐ญGSS_S_NO_TYPEmeans the token-id info could be parsed, but it didn't match any valid token_type.
(Note that this major status code has not been defined for GSS in RFC-1508. Until it is (if ever), SPKM implementations should instead return GSS_S_DEFECTIVE_TOKEN with both token_type and context_handle set to NULL. This basically means unrecognized token-id info gets treated the same as token-id info that couldn't be parsed ๐)
GSS_S_NO_CONTEXTmeans the context-id could be parsed, but it didn't match any valid context_handle ๐GSS_S_FAILUREmeans the mechanism type couldn't be parsed (for example, the token might be corrupted) ๐
SPKM_Parse_token() is used to return the mechanism type, token type, and context handle that match a given input token to an application ๐ GSS-API tokens are supposed to be opaque to the calling app, so this function lets the app figure out info about the token without breaking that opaqueness ๐ซถ The most important part is the token type, since the app can use it to decide which GSS function to call to get the token processed โจ
If all tokens are framed as suggested in RFC-1508, Appendix B (specified in both the Kerberos V5 GSS mechanism [KRB5] and this document), then any mechanism implementation should be able to return at least the mech_type parameter (with the others being NULL) for any uncorrupted input token ๐ If the mechanism implementation whose SPKM_Parse_token() function is being called does recognize the token, it can return token_type so the app can then call the correct GSS function. Finally, if the mechanism has a context-id field in its tokens (like SPKM does), an implementation can map the context-id to a context_handle and return that to the app ๐ This matters when an app has multiple contexts open at once, all using the same mechanism. When an incoming token arrives, the app can use this function to figure out not only which GSS function to call, but also which context_handle to use for the call ๐ฅ
Note that this function does no cryptographic processing to check whether tokens are valid. It just tries to parse the mech_type, token_type, and context-id fields of any token it's given ๐ So it's conceivable that an arbitrary buffer of data might start with random values that look like a valid mech_type, and SPKM_Parse_token() would then return incorrect info for that buffer. While conceivable, though, that situation is unlikely ๐ฆ
The SPKM_Parse_token() function is mandatory for SPKM-conformant implementations, but it's optional for applications ๐ So if an app only has one context open and can guess which GSS function to call (or is willing to put up with some error codes), it never needs to call SPKM_Parse_token() ๐ง Also, if this function ever moves up to the GSS-API level, SPKM_Parse_token() will be deprecated at that point in favour of GSS_Parse_token(), or whatever the new name and function spec turns out to be ๐ Last thing: no minor status return codes have been defined for this function at this time ๐ธ
6.2. The token_type Output Parameter ๐
okay so here are the token types that are defined โจ
GSS_INIT_TOKEN = 1
GSS_ACCEPT_TOKEN = 2
GSS_ERROR_TOKEN = 3
GSS_SIGN_TOKEN = GSS_GETMIC_TOKEN = 4
GSS_SEAL_TOKEN = GSS_WRAP_TOKEN = 5
GSS_DELETE_TOKEN = 6
bestie, every SPKM mechanism SHALL be able to map the token-id info inside every token (through the tag values in SPKMInnerContextToken or through the tok-id field) to one of those token types ๐
Then applications SHOULD be able to pick the right GSS function based on token_type. Like, if it's a GSS_INIT_TOKEN, the app calls gss_accept_sec_context(), and if it's a GSS_WRAP_TOKEN, the app calls gss_unwrap() ๐ฆ it's giving routing, and I'm obsessed.
6.3. The context_handle Output Parameter ๐ธ
so the SPKM implementation is in charge of keeping a mapping between the context-id value in every token and a context_handle, which is how each token finds its own context ๐ง Now, the context_handle can be figured out locally and may actually point at memory full of sensitive stuff on the local system, so setting the context-id equal to a computed context_handle just won't work in general ๐ And the reverse doesn't work either! The context_handle has to be handed back to the app by the very first call to gss_init_sec_context() or gss_accept_sec_context(), but making the context-id unique across all contexts at both ends might need both the initiator and the target to be involved in the math ๐ญ So context_handle and context-id MUST be computed separately, and the mechanism implementation MUST be able to map from one to the other by the time context establishment is done, at the latest ๐
here's how the context-id gets made during context establishment โจ Each SPKM implementation is responsible for generating a "fresh" random number, meaning one that (with high probability) hasn't been used before ๐ฒ Quick tea: there are NO cryptographic requirements on this number. It doesn't need to be unpredictable, it just needs to be fresh ๐ The initiator passes its random number to the target in the context-id field of the SPKM-REQ token. If no more context establishment tokens are coming (like unilateral authentication in SPKM-2), that value simply becomes the context-id. (If that's unacceptable to the target, then an error token MUST be generated ๐จ) Otherwise, the target makes its own random number and tacks it onto the end of the initiator's. That combined value becomes the context-id and gets used in SPKM-REP-TI and in all the later tokens over that context ๐
why is it so iconic? Because having BOTH peers contribute to the context-id gives each peer assurance of freshness, and that precludes replay attacks between contexts (where a token from an old context between two peers gets maliciously injected into a new context between the same or different peers) ๐ฅ The target doesn't get that assurance in unilateral authentication with SPKM-2, because it didn't help make the freshness of the computed context-id. Instead it has to trust the freshness of the initiator's random number, or reject the context ๐ฌ The key-src-bind field in SPKM-REQ is REQUIRED to be present for SPKM-2 unilateral authentication, precisely to help the target trust the freshness of this token (and its proposed context key) ๐ซถ
7. Security Considerations ๐
โ ๏ธ this one is serious, bestie: security issues are discussed throughout this memo, so please go read the whole thing and don't skip the scary parts ๐ญ
8. References ๐
- [Davi89]: D. W. Davies and W. L. Price, "Security for Computer Networks", Second Edition, John Wiley and Sons, New York, 1989.
- [FIPS-113]: National Bureau of Standards, Federal Information Processing Standard 113, "Computer Data Authentication", May 1985.
- [GSSv2]: Linn, J., "Generic Security Service Application Program Interface Version 2", Work in Progress.
- [Juen84]: R. R. Jueneman, C. H. Meyer and S. M. Matyas, Message Authentication with Manipulation Detection Codes, in Proceedings of the 1983 IEEE Symposium on Security and Privacy, IEEE Computer Society Press, 1984, pp.33-54.
- [KRB5]: Linn, J., "The Kerberos Version 5 GSS-API Mechanism", RFC 1964, June 1996.
- [PKCS1]: RSA Encryption Standard, Version 1.5, RSA Data Security, Inc., Nov. 1993.
- [PKCS3]: Diffie-Hellman Key-Agreement Standard, Version 1.4, RSA Data Security, Inc., Nov. 1993.
- [RFC-1321]: Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321.
- [RFC-1422]: Kent, S., "Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management", RFC 1422.
- [RFC-1423]: Balenson, D., "Privacy Enhancement for Internet Elecronic Mail: Part III: Algorithms, Modes, and Identifiers", RFC 1423.
- [RFC-1508]: Linn, J., "Generic Security Service Application Program Interface", RFC 1508.
- [RFC-1509]: Wray, J., "Generic Security Service Application Program Interface: C-bindings", RFC 1509.
- [RFC-1510]: Kohl J., and C. Neuman, "The Kerberos Network Authentication Service (V5)", RFC 1510.
- [9798]: ISO/IEC 9798-3, "Information technology - Security Techniques - Entity authentication mechanisms - Part 3: Entitiy authentication using a public key algorithm", ISO/IEC, 1993.
- [X.501]: ISO/IEC 9594-2, "Information Technology - Open Systems Interconnection - The Directory: Models", CCITT/ITU Recommendation X.501, 1993.
- [X.509]: ISO/IEC 9594-8, "Information Technology - Open Systems Interconnection - The Directory: Authentication Framework", CCITT/ITU Recommendation X.509, 1993.
- [X9.44]: ANSI, "Public Key Cryptography Using Reversible Algorithms for the Financial Services Industry: Transport of Symmetric Algorithm Keys Using RSA", X9.44-1993.
9. Author's Address ๐งโ๐ป
Carlisle Adams Bell-Northern Research P.O.Box 3511, Station C Ottawa, Ontario, CANADA K1Y 4H7
Phone: +1 613.763.9008 EMail: cadams@bnr.ca
Appendix A: ASN.1 Module Definition ๐งพ
SpkmGssTokens {iso(1) identified-organization(3) dod(6) internet(1)
security(5) mechanisms(5) spkm(1) spkmGssTokens(10)}
DEFINITIONS IMPLICIT TAGS ::=
BEGIN
-- EXPORTS ALL --
IMPORTS
Name
FROM InformationFramework {joint-iso-ccitt(2) ds(5) module(1)
informationFramework(1) 2}
Certificate, CertificateList, CertificatePair, AlgorithmIdentifier,
Validity
FROM AuthenticationFramework {joint-iso-ccitt(2) ds(5) module(1)
authenticationFramework(7) 2} ;
The ASN.1 types are the blueprint for every SPKM message, so this part is where the fields and tags get locked in ๐โจ
-- types --
SPKM-REQ ::= SEQUENCE {
requestToken REQ-TOKEN,
certif-data [0] CertificationData OPTIONAL,
auth-data [1] AuthorizationData OPTIONAL
}
CertificationData ::= SEQUENCE {
certificationPath [0] CertificationPath OPTIONAL,
certificateRevocationList [1] CertificateList OPTIONAL
} -- at least one of the above shall be present
CertificationPath ::= SEQUENCE {
userKeyId [0] OCTET STRING OPTIONAL,
userCertif [1] Certificate OPTIONAL,
verifKeyId [2] OCTET STRING OPTIONAL,
userVerifCertif [3] Certificate OPTIONAL,
theCACertificates [4] SEQUENCE OF CertificatePair OPTIONAL
} -- Presence of [2] or [3] implies that [0] or [1] must also be
-- present. Presence of [4] implies that at least one of [0], [1],
-- [2], and [3] must also be present.
REQ-TOKEN ::= SEQUENCE {
req-contents Req-contents,
algId AlgorithmIdentifier,
req-integrity Integrity -- "token" is Req-contents
}
Integrity ::= BIT STRING
-- If corresponding algId specifies a signing algorithm,
-- "Integrity" holds the result of applying the signing procedure
-- specified in algId to the BER-encoded octet string which results
-- from applying the hashing procedure (also specified in algId) to
-- the DER-encoded octets of "token".
-- Alternatively, if corresponding algId specifies a MACing
-- algorithm, "Integrity" holds the result of applying the MACing
-- procedure specified in algId to the DER-encoded octets of
-- "token"
Req-contents ::= SEQUENCE {
tok-id INTEGER (256), -- shall contain 0100 (hex)
context-id Random-Integer,
pvno BIT STRING,
timestamp UTCTime OPTIONAL, -- mandatory for SPKM-2
randSrc Random-Integer,
targ-name Name,
src-name [0] Name OPTIONAL,
req-data Context-Data,
validity [1] Validity OPTIONAL,
key-estb-set Key-Estb-Algs,
key-estb-req BIT STRING OPTIONAL,
key-src-bind OCTET STRING OPTIONAL
-- This field must be present for the case of SPKM-2
-- unilateral authen. if the K-ALG in use does not provide
-- such a binding (but is optional for all other cases).
-- The octet string holds the result of applying the
-- mandatory hashing procedure (in MANDATORY I-ALG;
-- see Section 2.1) as follows: MD5(src || context_key),
-- where "src" is the DER-encoded octets of src-name,
-- "context-key" is the symmetric key (i.e., the
-- unprotected version of what is transmitted in
-- key-estb-req), and "||" is the concatenation operation.
}
Random-Integer ::= BIT STRING
Context-Data ::= SEQUENCE {
channelId ChannelId OPTIONAL,
seq-number INTEGER OPTIONAL,
options Options,
conf-alg Conf-Algs,
intg-alg Intg-Algs,
owf-alg OWF-Algs
}
ChannelId ::= OCTET STRING
Options ::= BIT STRING {
delegation-state (0),
mutual-state (1),
replay-det-state (2),
sequence-state (3),
conf-avail (4),
integ-avail (5),
target-certif-data-required (6)
}
Conf-Algs ::= CHOICE {
algs [0] SEQUENCE OF AlgorithmIdentifier,
null [1] NULL
}
Intg-Algs ::= SEQUENCE OF AlgorithmIdentifier
OWF-Algs ::= SEQUENCE OF AlgorithmIdentifier
Key-Estb-Algs ::= SEQUENCE OF AlgorithmIdentifier
SPKM-REP-TI ::= SEQUENCE {
responseToken REP-TI-TOKEN,
certif-data CertificationData OPTIONAL
-- present if target-certif-data-required option was
} -- set to TRUE in SPKM-REQ
REP-TI-TOKEN ::= SEQUENCE {
rep-ti-contents Rep-ti-contents,
algId AlgorithmIdentifier,
rep-ti-integ Integrity -- "token" is Rep-ti-contents
}
Rep-ti-contents ::= SEQUENCE {
tok-id INTEGER (512), -- shall contain 0200 (hex)
context-id Random-Integer,
pvno [0] BIT STRING OPTIONAL,
timestamp UTCTime OPTIONAL, -- mandatory for SPKM-2
randTarg Random-Integer,
src-name [1] Name OPTIONAL,
targ-name Name,
randSrc Random-Integer,
rep-data Context-Data,
validity [2] Validity OPTIONAL,
key-estb-id AlgorithmIdentifier OPTIONAL,
key-estb-str BIT STRING OPTIONAL
}
SPKM-REP-IT ::= SEQUENCE {
responseToken REP-IT-TOKEN,
algId AlgorithmIdentifier,
rep-it-integ Integrity -- "token" is REP-IT-TOKEN
}
REP-IT-TOKEN ::= SEQUENCE {
tok-id INTEGER (768), -- shall contain 0300 (hex)
context-id Random-Integer,
randSrc Random-Integer,
randTarg Random-Integer,
targ-name Name,
src-name Name OPTIONAL,
key-estb-rep BIT STRING OPTIONAL
}
SPKM-ERROR ::= SEQUENCE {
errorToken ERROR-TOKEN,
algId AlgorithmIdentifier,
integrity Integrity -- "token" is ERROR-TOKEN
}
ERROR-TOKEN ::= SEQUENCE {
tok-id INTEGER (1024), -- shall contain 0400 (hex)
context-id Random-Integer
}
SPKM-MIC ::= SEQUENCE {
mic-header Mic-Header,
int-cksum BIT STRING
}
Mic-Header ::= SEQUENCE {
tok-id INTEGER (257), -- shall contain 0101 (hex)
context-id Random-Integer,
int-alg [0] AlgorithmIdentifier OPTIONAL,
snd-seq [1] SeqNum OPTIONAL
}
SeqNum ::= SEQUENCE {
num INTEGER,
dir-ind BOOLEAN
}
SPKM-WRAP ::= SEQUENCE {
wrap-header Wrap-Header,
wrap-body Wrap-Body
}
Wrap-Header ::= SEQUENCE {
tok-id INTEGER (513), -- shall contain 0201 (hex)
context-id Random-Integer,
int-alg [0] AlgorithmIdentifier OPTIONAL,
conf-alg [1] Conf-Alg OPTIONAL,
snd-seq [2] SeqNum OPTIONAL
}
Wrap-Body ::= SEQUENCE {
int-cksum BIT STRING,
data BIT STRING
}
Conf-Alg ::= CHOICE {
algId [0] AlgorithmIdentifier,
null [1] NULL
}
SPKM-DEL ::= SEQUENCE {
del-header Del-Header,
int-cksum BIT STRING
}
Del-Header ::= SEQUENCE {
tok-id INTEGER (769), -- shall contain 0301 (hex)
context-id Random-Integer,
int-alg [0] AlgorithmIdentifier OPTIONAL,
snd-seq [1] SeqNum OPTIONAL
}
-- other types --
-- from [RFC-1508] --
MechType ::= OBJECT IDENTIFIER
InitialContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE {
thisMech MechType,
innerContextToken SPKMInnerContextToken
} -- when thisMech is SPKM-1 or SPKM-2
SPKMInnerContextToken ::= CHOICE {
req [0] SPKM-REQ,
rep-ti [1] SPKM-REP-TI,
rep-it [2] SPKM-REP-IT,
error [3] SPKM-ERROR,
mic [4] SPKM-MIC,
wrap [5] SPKM-WRAP,
del [6] SPKM-DEL
}
-- from [RFC-1510] --
AuthorizationData ::= SEQUENCE OF SEQUENCE {
ad-type INTEGER,
ad-data OCTET STRING
}
-- object identifier assignments --
md5-DES-CBC OBJECT IDENTIFIER ::=
{iso(1) identified-organization(3) dod(6) internet(1) security(5)
integrity(3) md5-DES-CBC(1)}
sum64-DES-CBC OBJECT IDENTIFIER ::=
{iso(1) identified-organization(3) dod(6) internet(1) security(5)
integrity(3) sum64-DES-CBC(2)}
spkm-1 OBJECT IDENTIFIER ::=
{iso(1) identified-organization(3) dod(6) internet(1) security(5)
mechanisms(5) spkm(1) spkm-1(1)}
spkm-2 OBJECT IDENTIFIER ::=
{iso(1) identified-organization(3) dod(6) internet(1) security(5)
mechanisms(5) spkm(1) spkm-2(2)}
END
Appendix B: Imported Types โจ
okay so this appendix is the grab bag ๐ it's here "for completeness" and holds the relevant ASN.1 types pulled in from InformationFramework (1993), AuthenticationFramework (1993), and [PKCS3] ๐
AttributeType ::= OBJECT IDENTIFIER
AttributeValue ::= ANY
AttributeValueAssertion ::= SEQUENCE {AttributeType,AttributeValue}
RelativeDistinguishedName ::= SET OF AttributeValueAssertion
-- note that the 1993 InformationFramework module uses
-- different syntax for the above constructs
RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
DistinguishedName ::= RDNSequence
Name ::= CHOICE { -- only one for now
rdnSequence RDNSequence
}
Certificate ::= SEQUENCE {
certContents CertContents,
algID AlgorithmIdentifier,
sig BIT STRING
} -- sig holds the result of applying the signing procedure
-- specified in algId to the BER-encoded octet string which
-- results from applying the hashing procedure (also specified in
-- algId) to the DER-encoded octets of CertContents
CertContents ::= SEQUENCE {
version [0] Version DEFAULT v1,
serialNumber CertificateSerialNumber,
signature AlgorithmIdentifier,
issuer Name,
validity Validity,
subject Name,
subjectPublicKeyInfo SubjectPublicKeyInfo,
issuerUID [1] IMPLICIT UID OPTIONAL, -- used in v2 only
subjectUID [2] IMPLICIT UID OPTIONAL -- used in v2 only
}
Version ::= INTEGER {v1(0), v2(1)}
CertificateSerialNumber ::= INTEGER
UID ::= BIT STRING
Validity ::= SEQUENCE {
notBefore UTCTime,
notAfter UTCTime
}
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier,
subjectPublicKey BIT STRING
}
CertificatePair ::= SEQUENCE {
forward [0] Certificate OPTIONAL,
reverse [1] Certificate OPTIONAL
} -- at least one of the pair shall be present
CertificateList ::= SEQUENCE {
certListContents CertListContents,
algId AlgorithmIdentifier,
sig BIT STRING
} -- sig holds the result of applying the signing procedure
-- specified in algId to the BER-encoded octet string which
-- results from applying the hashing procedure (also specified in
-- algId) to the DER-encoded octets of CertListContents
CertListContents ::= SEQUENCE {
signature AlgorithmIdentifier,
issuer Name,
thisUpdate UTCTime,
nextUpdate UTCTime OPTIONAL,
revokedCertificates SEQUENCE OF SEQUENCE {
userCertificate CertificateSerialNumber,
revocationDate UTCTime } OPTIONAL
}
AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
parameter ANY DEFINED BY algorithm OPTIONAL
} -- note that the 1993 AuthenticationFramework module uses
-- different syntax for this construct
--from [PKCS3] (the parameter to be used with dhKeyAgreement) --
DHParameter ::= SEQUENCE {
prime INTEGER, -- p
base INTEGER, -- g
privateValueLength INTEGER OPTIONAL
}
๐ฆ where this page comes from
- ietf: rfc2025 1996-10
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms