Annotation of src/usr.bin/ssh/PROTOCOL.agent, Revision 1.1
1.1 ! djm 1: This describes the protocol used by OpenSSH's ssh-agent.
! 2:
! 3: OpenSSH's agent supports managing keys for the standard SSH protocol
! 4: 2 as well as the legacy SSH protocol 1. Support for these key types
! 5: is almost completely disjoint - in all but a few cases, operations on
! 6: protocol 2 keys cannot see or affect protocol 1 keys and vice-versa.
! 7:
! 8: Protocol 1 and protocol 2 keys are separated because of the differing
! 9: cryptographic usage: protocol 1 private RSA keys are used to decrypt
! 10: challenges that were encrypted with the corresponding public key,
! 11: whereas protocol 2 RSA private keys are used to sign challenges with
! 12: a private key for verification with the corresponding public key. It
! 13: is considered unsound practice to use the same key for signing and
! 14: encryption.
! 15:
! 16: With a couple of exceptions, the protocol message names used in this
! 17: document indicate which type of key the message relates to. SSH_*
! 18: messages refer to protocol 1 keys only. SSH2_* messages refer to
! 19: protocol 2 keys. Furthermore, the names also indicate whether message
! 20: is a request to the agent (*_AGENTC_*) or a reply from the agent
! 21: (*_AGENT_*). Section 3 below contains the mapping of the protocol
! 22: message names to their integer values.
! 23:
! 24: 1. Data types
! 25:
! 26: Because of it support for legacy SSH protocol 1 keys, OpenSSH's agent
! 27: protocol makes use of some data types not defined in RFC 4251.
! 28:
! 29: 1.1 uint16
! 30:
! 31: The "uint16" data type is a simple MSB-first 16 bit unsigned integer
! 32: encoded in two bytes.
! 33:
! 34: 1.2 mpint1
! 35:
! 36: The "mpint1" type represents an arbitrary precision integer (bignum).
! 37: Its format is as follows:
! 38:
! 39: uint16 bits
! 40: byte[(bits + 7) / 8] bignum
! 41:
! 42: "bignum" contains an unsigned arbitrary precision integer encoded as
! 43: eight bits per byte in big-endian (MSB first) format.
! 44:
! 45: Note the difference between the "mpint1" encoding an the the "mpint"
! 46: encoding defined in RFC 4251. Also note that the length of the encoded
! 47: integer is specified in bits, not bytes and that the byte length of of
! 48: the integer must be calculated by rounding up the number of bits to the
! 49: nearest eight.
! 50:
! 51: 2. Protocol Messages
! 52:
! 53: All protocol messages are prefixed with their length in bytes, encoded
! 54: as a 32 bit unsigned integer. Specifically:
! 55:
! 56: uint32 message_length
! 57: byte[message_length] message
! 58:
! 59: The following message description refer only to the content the
! 60: "message" field.
! 61:
! 62: 2.1 Generic server responses
! 63:
! 64: The following generic messages may be sent by the server in response to
! 65: requests from the client. On success the agent may reply either with:
! 66:
! 67: byte SSH_AGENT_SUCCESS
! 68:
! 69: or a request-specific success message.
! 70:
! 71: On failure, the agent may reply with:
! 72:
! 73: byte SSH_AGENT_FAILURE
! 74:
! 75: SSH_AGENT_FAILURE messages are also sent in reply to unknown request
! 76: types.
! 77:
! 78: 2.2 Adding keys to the agent
! 79:
! 80: Keys are added to the agent using the SSH_AGENTC_ADD_RSA_IDENTITY and
! 81: SSH2_AGENTC_ADD_IDENTITY requests for protocol 1 and protocol 2 keys
! 82: respectively.
! 83:
! 84: Two variants of these requests are SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
! 85: and SSH2_AGENTC_ADD_ID_CONSTRAINED - these add keys with optional
! 86: "constraints" on their usage.
! 87:
! 88: OpenSSH may be built with support for keys hosted on a smartcard
! 89: or other hardware security module. These keys may added
! 90: to the agent using the SSH_AGENTC_ADD_SMARTCARD_KEY and
! 91: SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED requests
! 92:
! 93: 2.2.1 Key constraints
! 94:
! 95: The OpenSSH agent supports some basic optional constraints on key usage.
! 96: At present there are two constraints defined.
! 97:
! 98: The first constraint limits the validity duration of a key. It is
! 99: encoded as:
! 100:
! 101: byte SSH_AGENT_CONSTRAIN_LIFETIME
! 102: uint32 seconds
! 103:
! 104: Where "seconds" contains the number of seconds that the key shall remain
! 105: valid measured from the moment that the agent receives it. After the
! 106: validity period has expired, OpenSSH's agent will erase these keys from
! 107: memory.
! 108:
! 109: The second constraint requires the agent to seek explicit user
! 110: confirmation before performing private key operations with the loaded
! 111: key. This constraint is encoded as:
! 112:
! 113: byte SSH_AGENT_CONSTRAIN_CONFIRM
! 114:
! 115: Zero or more constraints may be specified when adding a key with one
! 116: of the *_CONSTRAINED requests. Multiple constraints are appended
! 117: consecutively to the end of the request:
! 118:
! 119: byte constraint1_type
! 120: .... constraint1_date
! 121: byte constraint2_type
! 122: .... constraint2_date
! 123: ....
! 124: byte constraintN_type
! 125: .... constraintN_date
! 126:
! 127: Such a sequence of zero or more constraints will be referred to below
! 128: as "constraint[]". Agents may determine whether there are constraints
! 129: by checking whether additional data exists in the an "add key" request
! 130: after the key data itself. OpenSSH will refuse to add a key if it
! 131: contains unknown constraints.
! 132:
! 133: 2.2.2 Add protocol 1 key
! 134:
! 135: A client may add a protocol 1 key to an agent with the following
! 136: request:
! 137:
! 138: byte SSH_AGENTC_ADD_RSA_IDENTITY or
! 139: SSH_AGENTC_ADD_RSA_ID_CONSTRAINED
! 140: uint32 ignored
! 141: mpint1 rsa_n
! 142: mpint1 rsa_e
! 143: mpint1 rsa_d
! 144: mpint1 rsa_iqmp
! 145: mpint1 rsa_q
! 146: mpint1 rsa_p
! 147: string key_comment
! 148: constraint[] key_constraints
! 149:
! 150: Note that there is some redundancy in the key parameters; a key could be
! 151: fully specified using just rsa_q, rsa_p and rsa_e at the cost of extra
! 152: computation.
! 153:
! 154: "key_constraints" may only be present if the request type is
! 155: SSH_AGENTC_ADD_RSA_IDENTITY.
! 156:
! 157: The agent will reply with a SSH_AGENT_SUCCESS if the key has been
! 158: successfully added or a SSH_AGENT_FAILURE if an error occurred.
! 159:
! 160: 2.2.3 Add protocol 2 key
! 161:
! 162: The OpenSSH agent supports DSA and RSA keys for protocol 2. DSA keys may
! 163: be added using the following request
! 164:
! 165: byte SSH2_AGENTC_ADD_IDENTITY or
! 166: SSH2_AGENTC_ADD_ID_CONSTRAINED
! 167: string "ssh-dss"
! 168: mpint dsa_p
! 169: mpint dsa_q
! 170: mpint dsa_g
! 171: mpint dsa_public_key
! 172: mpint dsa_private_key
! 173: string key_comment
! 174: constraint[] key_constraints
! 175:
! 176: RSA keys may be added with this request:
! 177:
! 178: byte SSH2_AGENTC_ADD_IDENTITY or
! 179: SSH2_AGENTC_ADD_ID_CONSTRAINED
! 180: string "ssh-rsa"
! 181: mpint rsa_n
! 182: mpint rsa_e
! 183: mpint rsa_d
! 184: mpint rsa_iqmp
! 185: mpint rsa_p
! 186: mpint rsa_q
! 187: string key_comment
! 188: constraint[] key_constraints
! 189:
! 190: Note that the 'rsa_p' and 'rsa_q' parameters are send in the reverse
! 191: order to the protocol 1 add keys message. As with the corresponding
! 192: protocol 1 "add key" request, the private key is overspecified to avoid
! 193: redundant processing.
! 194:
! 195: For both DSA and RSA key add requests, "key_constraints" may only be
! 196: present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
! 197:
! 198: The agent will reply with a SSH_AGENT_SUCCESS if the key has been
! 199: successfully added or a SSH_AGENT_FAILURE if an error occurred.
! 200:
! 201: 2.2.4 Loading keys from a smartcard
! 202:
! 203: The OpenSSH agent may have optional smartcard support built in to it. If
! 204: so, it supports an operation to load keys from a smartcard. Technically,
! 205: only the public components of the keys are loaded into the agent so
! 206: this operation really arranges for future private key operations to be
! 207: delegated to the smartcard.
! 208:
! 209: byte SSH_AGENTC_ADD_SMARTCARD_KEY or
! 210: SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED
! 211: string reader_id
! 212: string pin
! 213: constraint[] key_constraints
! 214:
! 215: "reader_id" the an identifier to a smartcard reader and "pin"
! 216: is a PIN or passphrase used to unlock the private key(s) on the
! 217: device. "key_constraints" may only be present if the request type is
! 218: SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED.
! 219:
! 220: This operation may load all SSH keys that are unlocked using the
! 221: "pin" on the specified reader. The type of key loaded (protocol 1
! 222: or protocol 2) will be specified by the smartcard itself, it is not
! 223: client-specified.
! 224:
! 225: The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
! 226: been successfully loaded or a SSH_AGENT_FAILURE if an error occurred.
! 227: The agent will also return SSH_AGENT_FAILURE if it does not support
! 228: smartcards.
! 229:
! 230: 2.3 Removing multiple keys
! 231:
! 232: A client may request that an agent delete all protocol 1 keys using the
! 233: following request:
! 234:
! 235: byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES
! 236:
! 237: This message requests the deletion of all protocol 2 keys:
! 238:
! 239: byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES
! 240:
! 241: On success, the agent will delete all keys of the requested type and
! 242: reply with a SSH_AGENT_SUCCESS message. If an error occurred, the agent
! 243: will reply with SSH_AGENT_FAILURE.
! 244:
! 245: Note that, to delete all keys (both protocol 1 and 2), a client
! 246: must send both a SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES and a
! 247: SSH2_AGENTC_REMOVE_ALL_IDENTITIES request.
! 248:
! 249: 2.4 Removing specific keys
! 250:
! 251: 2.4.1 Removing a protocol 1 key
! 252:
! 253: Removal of a protocol 1 key may be requested with the following message:
! 254:
! 255: byte SSH_AGENTC_REMOVE_RSA_IDENTITY
! 256: uint32 key_bits
! 257: mpint1 rsa_e
! 258: mpint1 rsa_n
! 259:
! 260: Note that key_bits is strictly redundant, as it may be inferred by the
! 261: length of rsa_n.
! 262:
! 263: The agent will delete any private key matching the specified public key
! 264: and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
! 265: return SSH_AGENT_FAILURE.
! 266:
! 267: 2.4.2 Removing a protocol 2 key
! 268:
! 269: Protocol 2 keys may be removed with the following request:
! 270:
! 271: byte SSH2_AGENTC_REMOVE_IDENTITY
! 272: byte[n] key_blob
! 273:
! 274: Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
! 275: Algorithms" for either of the supported key types: "ssh-dss" or
! 276: "ssh-rsa".
! 277:
! 278: The agent will delete any private key matching the specified public key
! 279: and return SSH_AGENT_SUCCESS. If no such key was found, the agent will
! 280: return SSH_AGENT_FAILURE.
! 281:
! 282: 2.4.3 Removing keys loaded from a smartcard
! 283:
! 284: A client may request that a server remove one or more smartcard-hosted
! 285: keys using this message:
! 286:
! 287: byte SSH_AGENTC_REMOVE_SMARTCARD_KEY
! 288: string reader_id
! 289: string pin
! 290:
! 291: "reader_id" the an identifier to a smartcard reader and "pin" is a PIN
! 292: or passphrase used to unlock the private key(s) on the device.
! 293:
! 294: When this message is received, and if the agent supports
! 295: smartcard-hosted keys, it will delete all keys that are hosted on the
! 296: specified smartcard that may be accessed with the given "pin".
! 297:
! 298: The agent will reply with a SSH_AGENT_SUCCESS if one or more keys have
! 299: been successfully removed or a SSH_AGENT_FAILURE if an error occurred.
! 300: The agent will also return SSH_AGENT_FAILURE if it does not support
! 301: smartcards.
! 302:
! 303: 2.5 Requesting a list of known keys
! 304:
! 305: An agent may be requested to list which keys it holds. Different
! 306: requests exist for protocol 1 and protocol 2 keys.
! 307:
! 308: 2.5.1 Requesting a list of protocol 1 keys
! 309:
! 310: To request a list of protocol 1 keys that are held in the agent, a
! 311: client may send the following message:
! 312:
! 313: byte SSH_AGENTC_REQUEST_RSA_IDENTITIES
! 314:
! 315: The agent will reply with the following message:
! 316:
! 317: byte SSH_AGENT_RSA_IDENTITIES_ANSWER
! 318: uint32 num_keys
! 319:
! 320: Followed by zero or more consecutive keys, encoded as:
! 321:
! 322: uint32 bits
! 323: mpint1 rsa_e
! 324: mpint1 rsa_n
! 325: string key_comment
! 326:
! 327: 2.5.2 Requesting a list of protocol 2 keys
! 328:
! 329: A client may send the following message to request a list of keys
! 330: protocol 2 keys that are stored in the agent:
! 331:
! 332: byte SSH2_AGENTC_REQUEST_IDENTITIES
! 333:
! 334: The agent will reply with the following message header:
! 335:
! 336: byte SSH2_AGENT_IDENTITIES_ANSWER
! 337: uint32 num_keys
! 338:
! 339: Followed by zero or more consecutive keys, encoded as:
! 340:
! 341: byte[n] key_blob
! 342: string key_comment
! 343:
! 344: Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
! 345: Algorithms" for either of the supported key types: "ssh-dss" or
! 346: "ssh-rsa".
! 347:
! 348: 2.6 Private key operations
! 349:
! 350: The purpose of the agent is to perform private key operations, such as
! 351: signing and encryption without requiring a passphrase to unlock the
! 352: key and without allowing the private key itself to be exposed. There
! 353: are separate requests for the protocol 1 and protocol 2 private key
! 354: operations.
! 355:
! 356: 2.6.1 Protocol 1 private key challenge
! 357:
! 358: The private key operation used in version 1 of the SSH protocol is
! 359: decrypting a challenge that has been encrypted with a public key.
! 360: It may be requested using this message:
! 361:
! 362: byte SSH_AGENTC_RSA_CHALLENGE
! 363: uint32 ignored
! 364: mpint1 rsa_e
! 365: mpint1 rsa_n
! 366: mpint1 encrypted_challenge
! 367: byte[16] session_id
! 368: uint32 response_type /* must be 1 */
! 369:
! 370: "rsa_e" and "rsa_n" are used to identify which private key to use.
! 371: "encrypted_challenge" is a challenge blob that has (presumably)
! 372: been encrypted with the public key and must be in the range
! 373: 1 <= encrypted_challenge < 2^256. "session_id" is the SSH protocol 1
! 374: session ID (computed from the server host key, the server semi-ephemeral
! 375: key and the session cookie.)
! 376:
! 377: "ignored" and "response_type" exist for compatibility with legacy
! 378: implementations. "response_type" must be equal to 1; other response
! 379: types are not supported.
! 380:
! 381: On receiving this request, the server decrypts the "encrypted_challenge"
! 382: using private key matching the supplied (rsa_e, rsa_n) values. For
! 383: the response derivation, the decrypted challenge is represented as an
! 384: unsigned, big-endian integer encoded in a 32 byte buffer (i.e. values
! 385: smaller than 2^248 will have leading 0 bytes).
! 386:
! 387: The response value is then calculated as:
! 388:
! 389: response = MD5(decrypted_challenge || session_id)
! 390:
! 391: and returned in the following message
! 392:
! 393: byte SSH_AGENT_RSA_RESPONSE
! 394: byte[16] response
! 395:
! 396: If the agent cannot find the key specified by the supplied (rsa_e,
! 397: rsa_n) then it will return SSH_AGENT_FAILURE.
! 398:
! 399: 2.6.2 Protocol 2 private key signature request
! 400:
! 401: A client may use the following message to request signing of data using
! 402: a protocol 2 key:
! 403:
! 404: byte SSH2_AGENTC_SIGN_REQUEST
! 405: string key_blob
! 406: string data
! 407: uint32 flags
! 408:
! 409: Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
! 410: Algorithms" for either of the supported key types: "ssh-dss" or
! 411: "ssh-rsa". "flags" is a bit-mask, but at present only one possible value
! 412: is defined (see below for its meaning):
! 413:
! 414: SSH_AGENT_OLD_SIGNATURE 1
! 415:
! 416: Upon receiving this request, the agent will look up the private key that
! 417: corresponds to the public key contained in key_blob. It will use this
! 418: private key to sign the "data" and produce a signature blob using the
! 419: key type-specific method described in RFC 4253 section 6.6 "Public Key
! 420: Algorithms".
! 421:
! 422: An exception to this is for "ssh-dss" keys where the "flags" word
! 423: contains the value SSH_AGENT_OLD_SIGNATURE. In this case, a legacy
! 424: signature encoding is used in lieu of the standard one. In this case,
! 425: the DSA signature blob is encoded as:
! 426:
! 427: byte[40] signature
! 428:
! 429: The signature will be returned in the response message:
! 430:
! 431: byte SSH2_AGENT_SIGN_RESPONSE
! 432: string signature_blob
! 433:
! 434: If the agent cannot find the key specified by the supplied key_blob then
! 435: it will return SSH_AGENT_FAILURE.
! 436:
! 437: 2.7 Locking or unlocking an agent
! 438:
! 439: The agent supports temporary locking with a passphrase to suspend
! 440: processing of sensitive operations until it has been unlocked with the
! 441: same passphrase. To lock an agent, a client send the following request:
! 442:
! 443: byte SSH_AGENTC_LOCK
! 444: string passphrase
! 445:
! 446: Upon receipt of this message and if the agent is not already locked,
! 447: it will suspend processing requests and return a SSH_AGENT_SUCCESS
! 448: reply. If the agent is already locked, it will return SSH_AGENT_FAILURE.
! 449:
! 450: While locked, the agent will refuse all requests except
! 451: SSH_AGENTC_UNLOCK, SSH_AGENTC_REQUEST_RSA_IDENTITIES and
! 452: SSH2_AGENTC_REQUEST_IDENTITIES. The "request identities" requests are
! 453: treated specially by a locked agent: it will always return an empty list
! 454: of keys.
! 455:
! 456: To unlock an agent, a client may request:
! 457:
! 458: byte SSH_AGENTC_UNLOCK
! 459: string passphrase
! 460:
! 461: If the passphrase matches and the agent is locked, then it will resume
! 462: processing all requests and return SSH_AGENT_SUCCESS. If the agent
! 463: is not locked or the passphrase does not match then it will return
! 464: SSH_AGENT_FAILURE.
! 465:
! 466: Locking and unlocking affects both protocol 1 and protocol 2 keys.
! 467:
! 468: 3. Protocol message numbers
! 469:
! 470: 3.1 Requests from client to agent for protocol 1 key operations
! 471:
! 472: SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
! 473: SSH_AGENTC_RSA_CHALLENGE 3
! 474: SSH_AGENTC_ADD_RSA_IDENTITY 7
! 475: SSH_AGENTC_REMOVE_RSA_IDENTITY 8
! 476: SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
! 477: SSH_AGENTC_ADD_RSA_ID_CONSTRAINED 24
! 478:
! 479: 3.2 Requests from client to agent for protocol 2 key operations
! 480:
! 481: SSH2_AGENTC_REQUEST_IDENTITIES 11
! 482: SSH2_AGENTC_SIGN_REQUEST 13
! 483: SSH2_AGENTC_ADD_IDENTITY 17
! 484: SSH2_AGENTC_REMOVE_IDENTITY 18
! 485: SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
! 486: SSH2_AGENTC_ADD_ID_CONSTRAINED 25
! 487:
! 488: 3.3 Key-type independent requests from client to agent
! 489:
! 490: SSH_AGENTC_ADD_SMARTCARD_KEY 20
! 491: SSH_AGENTC_REMOVE_SMARTCARD_KEY 21
! 492: SSH_AGENTC_LOCK 22
! 493: SSH_AGENTC_UNLOCK 23
! 494: SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
! 495:
! 496: 3.4 Generic replies from agent to client
! 497:
! 498: SSH_AGENT_FAILURE 5
! 499: SSH_AGENT_SUCCESS 6
! 500:
! 501: 3.5 Replies from agent to client for protocol 1 key operations
! 502:
! 503: SSH_AGENT_RSA_IDENTITIES_ANSWER 2
! 504: SSH_AGENT_RSA_RESPONSE 4
! 505:
! 506: 3.6 Replies from agent to client for protocol 2 key operations
! 507:
! 508: SSH2_AGENT_IDENTITIES_ANSWER 12
! 509: SSH2_AGENT_SIGN_RESPONSE 14
! 510:
! 511: 3.7 Key constraint identifiers
! 512:
! 513: SSH_AGENT_CONSTRAIN_LIFETIME 1
! 514: SSH_AGENT_CONSTRAIN_CONFIRM 2
! 515:
! 516: $OpenBSD$