diff options
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | PROTOCOL | 45 | ||||
-rw-r--r-- | PROTOCOL.agent | 44 | ||||
-rw-r--r-- | PROTOCOL.certkeys | 89 | ||||
-rw-r--r-- | auth2-jpake.c | 7 | ||||
-rw-r--r-- | authfd.c | 20 | ||||
-rw-r--r-- | authfile.c | 32 | ||||
-rw-r--r-- | bufec.c | 140 | ||||
-rw-r--r-- | buffer.h | 9 | ||||
-rw-r--r-- | dns.c | 3 | ||||
-rw-r--r-- | kex.c | 10 | ||||
-rw-r--r-- | kex.h | 16 | ||||
-rw-r--r-- | kexecdh.c | 108 | ||||
-rw-r--r-- | kexecdhc.c | 156 | ||||
-rw-r--r-- | kexecdhs.c | 161 | ||||
-rw-r--r-- | key.c | 541 | ||||
-rw-r--r-- | key.h | 23 | ||||
-rw-r--r-- | monitor.c | 3 | ||||
-rw-r--r-- | monitor_wrap.c | 3 | ||||
-rw-r--r-- | myproposal.h | 32 | ||||
-rw-r--r-- | packet.c | 14 | ||||
-rw-r--r-- | packet.h | 5 | ||||
-rw-r--r-- | pathnames.h | 4 | ||||
-rw-r--r-- | readconf.c | 8 | ||||
-rw-r--r-- | ssh-add.1 | 13 | ||||
-rw-r--r-- | ssh-add.c | 3 | ||||
-rw-r--r-- | ssh-agent.1 | 11 | ||||
-rw-r--r-- | ssh-agent.c | 60 | ||||
-rw-r--r-- | ssh-ecdsa.c | 160 | ||||
-rw-r--r-- | ssh-keygen.1 | 9 | ||||
-rw-r--r-- | ssh-keygen.c | 40 | ||||
-rw-r--r-- | ssh-keyscan.1 | 20 | ||||
-rw-r--r-- | ssh-keyscan.c | 13 | ||||
-rw-r--r-- | ssh-keysign.8 | 6 | ||||
-rw-r--r-- | ssh.1 | 25 | ||||
-rw-r--r-- | ssh.c | 27 | ||||
-rw-r--r-- | ssh2.h | 6 | ||||
-rw-r--r-- | ssh_config.5 | 23 | ||||
-rw-r--r-- | sshconnect.c | 4 | ||||
-rw-r--r-- | sshconnect2.c | 3 | ||||
-rw-r--r-- | sshd.8 | 20 | ||||
-rw-r--r-- | sshd.c | 7 | ||||
-rw-r--r-- | sshd_config.5 | 12 | ||||
-rw-r--r-- | uuencode.c | 4 | ||||
-rw-r--r-- | uuencode.h | 4 |
45 files changed, 1793 insertions, 173 deletions
@@ -25,6 +25,29 @@ | |||
25 | * actually, we allow a single one at the end of the string for now because | 25 | * actually, we allow a single one at the end of the string for now because |
26 | we don't know how many deployed implementations get this wrong, but don't | 26 | we don't know how many deployed implementations get this wrong, but don't |
27 | count on this to remain indefinitely. | 27 | count on this to remain indefinitely. |
28 | - djm@cvs.openbsd.org 2010/08/31 11:54:45 | ||
29 | [PROTOCOL PROTOCOL.agent PROTOCOL.certkeys auth2-jpake.c authfd.c] | ||
30 | [authfile.c buffer.h dns.c kex.c kex.h key.c key.h monitor.c] | ||
31 | [monitor_wrap.c myproposal.h packet.c packet.h pathnames.h readconf.c] | ||
32 | [ssh-add.1 ssh-add.c ssh-agent.1 ssh-agent.c ssh-keygen.1 ssh-keygen.c] | ||
33 | [ssh-keyscan.1 ssh-keyscan.c ssh-keysign.8 ssh.1 ssh.c ssh2.h] | ||
34 | [ssh_config.5 sshconnect.c sshconnect2.c sshd.8 sshd.c sshd_config.5] | ||
35 | [uuencode.c uuencode.h bufec.c kexecdh.c kexecdhc.c kexecdhs.c ssh-ecdsa.c] | ||
36 | Implement Elliptic Curve Cryptography modes for key exchange (ECDH) and | ||
37 | host/user keys (ECDSA) as specified by RFC5656. ECDH and ECDSA offer | ||
38 | better performance than plain DH and DSA at the same equivalent symmetric | ||
39 | key length, as well as much shorter keys. | ||
40 | |||
41 | Only the mandatory sections of RFC5656 are implemented, specifically the | ||
42 | three REQUIRED curves nistp256, nistp384 and nistp521 and only ECDH and | ||
43 | ECDSA. Point compression (optional in RFC5656 is NOT implemented). | ||
44 | |||
45 | Certificate host and user keys using the new ECDSA key types are supported. | ||
46 | |||
47 | Note that this code has not been tested for interoperability and may be | ||
48 | subject to change. | ||
49 | |||
50 | feedback and ok markus@ | ||
28 | 51 | ||
29 | 20100827 | 52 | 20100827 |
30 | - (dtucker) [contrib/redhat/sshd.init] Bug #1810: initlog is deprecated, | 53 | - (dtucker) [contrib/redhat/sshd.init] Bug #1810: initlog is deprecated, |
@@ -12,7 +12,9 @@ are individually implemented as extensions described below. | |||
12 | The protocol used by OpenSSH's ssh-agent is described in the file | 12 | The protocol used by OpenSSH's ssh-agent is described in the file |
13 | PROTOCOL.agent | 13 | PROTOCOL.agent |
14 | 14 | ||
15 | 1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com" | 15 | 1. Transport protocol changes |
16 | |||
17 | 1.1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com" | ||
16 | 18 | ||
17 | This is a new transport-layer MAC method using the UMAC algorithm | 19 | This is a new transport-layer MAC method using the UMAC algorithm |
18 | (rfc4418). This method is identical to the "umac-64" method documented | 20 | (rfc4418). This method is identical to the "umac-64" method documented |
@@ -20,7 +22,7 @@ in: | |||
20 | 22 | ||
21 | http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt | 23 | http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt |
22 | 24 | ||
23 | 2. transport: Protocol 2 compression algorithm "zlib@openssh.com" | 25 | 1.2. transport: Protocol 2 compression algorithm "zlib@openssh.com" |
24 | 26 | ||
25 | This transport-layer compression method uses the zlib compression | 27 | This transport-layer compression method uses the zlib compression |
26 | algorithm (identical to the "zlib" method in rfc4253), but delays the | 28 | algorithm (identical to the "zlib" method in rfc4253), but delays the |
@@ -31,14 +33,27 @@ The method is documented in: | |||
31 | 33 | ||
32 | http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt | 34 | http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt |
33 | 35 | ||
34 | 3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com" and | 36 | 1.3. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com", |
35 | "ssh-dsa-cert-v00@openssh.com" | 37 | "ssh-dsa-cert-v00@openssh.com", |
38 | "ecdsa-sha2-nistp256-cert-v01@openssh.com", | ||
39 | "ecdsa-sha2-nistp384-cert-v01@openssh.com" and | ||
40 | "ecdsa-sha2-nistp521-cert-v01@openssh.com" | ||
36 | 41 | ||
37 | OpenSSH introduces two new public key algorithms to support certificate | 42 | OpenSSH introduces new public key algorithms to support certificate |
38 | authentication for users and hostkeys. These methods are documented in | 43 | authentication for users and hostkeys. These methods are documented in |
39 | the file PROTOCOL.certkeys | 44 | the file PROTOCOL.certkeys |
40 | 45 | ||
41 | 4. connection: Channel write close extension "eow@openssh.com" | 46 | 1.4. transport: Elliptic Curve cryptography |
47 | |||
48 | OpenSSH supports ECC key exchange and public key authentication as | ||
49 | specified in RFC5656. Only the ecdsa-sha2-nistp256, ecdsa-sha2-nistp384 | ||
50 | and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic | ||
51 | curve points encoded using point compression are NOT accepted or | ||
52 | generated. | ||
53 | |||
54 | 2. Connection protocol changes | ||
55 | |||
56 | 2.1. connection: Channel write close extension "eow@openssh.com" | ||
42 | 57 | ||
43 | The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF | 58 | The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF |
44 | message to allow an endpoint to signal its peer that it will send no | 59 | message to allow an endpoint to signal its peer that it will send no |
@@ -77,8 +92,8 @@ message is only sent to OpenSSH peers (identified by banner). | |||
77 | Other SSH implementations may be whitelisted to receive this message | 92 | Other SSH implementations may be whitelisted to receive this message |
78 | upon request. | 93 | upon request. |
79 | 94 | ||
80 | 5. connection: disallow additional sessions extension | 95 | 2.2. connection: disallow additional sessions extension |
81 | "no-more-sessions@openssh.com" | 96 | "no-more-sessions@openssh.com" |
82 | 97 | ||
83 | Most SSH connections will only ever request a single session, but a | 98 | Most SSH connections will only ever request a single session, but a |
84 | attacker may abuse a running ssh client to surreptitiously open | 99 | attacker may abuse a running ssh client to surreptitiously open |
@@ -105,7 +120,7 @@ of this message, the no-more-sessions request is only sent to OpenSSH | |||
105 | servers (identified by banner). Other SSH implementations may be | 120 | servers (identified by banner). Other SSH implementations may be |
106 | whitelisted to receive this message upon request. | 121 | whitelisted to receive this message upon request. |
107 | 122 | ||
108 | 6. connection: Tunnel forward extension "tun@openssh.com" | 123 | 2.3. connection: Tunnel forward extension "tun@openssh.com" |
109 | 124 | ||
110 | OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com" | 125 | OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com" |
111 | channel type. This channel type supports forwarding of network packets | 126 | channel type. This channel type supports forwarding of network packets |
@@ -166,7 +181,9 @@ The contents of the "data" field for layer 2 packets is: | |||
166 | The "frame" field contains an IEEE 802.3 Ethernet frame, including | 181 | The "frame" field contains an IEEE 802.3 Ethernet frame, including |
167 | header. | 182 | header. |
168 | 183 | ||
169 | 7. sftp: Reversal of arguments to SSH_FXP_SYMLINK | 184 | 3. SFTP protocol changes |
185 | |||
186 | 3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK | ||
170 | 187 | ||
171 | When OpenSSH's sftp-server was implemented, the order of the arguments | 188 | When OpenSSH's sftp-server was implemented, the order of the arguments |
172 | to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, | 189 | to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, |
@@ -179,7 +196,7 @@ SSH_FXP_SYMLINK as follows: | |||
179 | string targetpath | 196 | string targetpath |
180 | string linkpath | 197 | string linkpath |
181 | 198 | ||
182 | 8. sftp: Server extension announcement in SSH_FXP_VERSION | 199 | 3.2. sftp: Server extension announcement in SSH_FXP_VERSION |
183 | 200 | ||
184 | OpenSSH's sftp-server lists the extensions it supports using the | 201 | OpenSSH's sftp-server lists the extensions it supports using the |
185 | standard extension announcement mechanism in the SSH_FXP_VERSION server | 202 | standard extension announcement mechanism in the SSH_FXP_VERSION server |
@@ -200,7 +217,7 @@ ever changed in an incompatible way. The server MAY advertise the same | |||
200 | extension with multiple versions (though this is unlikely). Clients MUST | 217 | extension with multiple versions (though this is unlikely). Clients MUST |
201 | check the version number before attempting to use the extension. | 218 | check the version number before attempting to use the extension. |
202 | 219 | ||
203 | 9. sftp: Extension request "posix-rename@openssh.com" | 220 | 3.3. sftp: Extension request "posix-rename@openssh.com" |
204 | 221 | ||
205 | This operation provides a rename operation with POSIX semantics, which | 222 | This operation provides a rename operation with POSIX semantics, which |
206 | are different to those provided by the standard SSH_FXP_RENAME in | 223 | are different to those provided by the standard SSH_FXP_RENAME in |
@@ -217,7 +234,7 @@ rename(oldpath, newpath) and will respond with a SSH_FXP_STATUS message. | |||
217 | This extension is advertised in the SSH_FXP_VERSION hello with version | 234 | This extension is advertised in the SSH_FXP_VERSION hello with version |
218 | "1". | 235 | "1". |
219 | 236 | ||
220 | 10. sftp: Extension requests "statvfs@openssh.com" and | 237 | 3.4. sftp: Extension requests "statvfs@openssh.com" and |
221 | "fstatvfs@openssh.com" | 238 | "fstatvfs@openssh.com" |
222 | 239 | ||
223 | These requests correspond to the statvfs and fstatvfs POSIX system | 240 | These requests correspond to the statvfs and fstatvfs POSIX system |
@@ -258,4 +275,4 @@ The values of the f_flag bitmask are as follows: | |||
258 | Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are | 275 | Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are |
259 | advertised in the SSH_FXP_VERSION hello with version "2". | 276 | advertised in the SSH_FXP_VERSION hello with version "2". |
260 | 277 | ||
261 | $OpenBSD: PROTOCOL,v 1.15 2010/02/26 20:29:54 djm Exp $ | 278 | $OpenBSD: PROTOCOL,v 1.16 2010/08/31 11:54:45 djm Exp $ |
diff --git a/PROTOCOL.agent b/PROTOCOL.agent index b34fcd318..de94d037d 100644 --- a/PROTOCOL.agent +++ b/PROTOCOL.agent | |||
@@ -159,8 +159,8 @@ successfully added or a SSH_AGENT_FAILURE if an error occurred. | |||
159 | 159 | ||
160 | 2.2.3 Add protocol 2 key | 160 | 2.2.3 Add protocol 2 key |
161 | 161 | ||
162 | The OpenSSH agent supports DSA and RSA keys for protocol 2. DSA keys may | 162 | The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA |
163 | be added using the following request | 163 | keys may be added using the following request |
164 | 164 | ||
165 | byte SSH2_AGENTC_ADD_IDENTITY or | 165 | byte SSH2_AGENTC_ADD_IDENTITY or |
166 | SSH2_AGENTC_ADD_ID_CONSTRAINED | 166 | SSH2_AGENTC_ADD_ID_CONSTRAINED |
@@ -182,6 +182,30 @@ DSA certificates may be added with: | |||
182 | string key_comment | 182 | string key_comment |
183 | constraint[] key_constraints | 183 | constraint[] key_constraints |
184 | 184 | ||
185 | ECDSA keys may be added using the following request | ||
186 | |||
187 | byte SSH2_AGENTC_ADD_IDENTITY or | ||
188 | SSH2_AGENTC_ADD_ID_CONSTRAINED | ||
189 | string "ecdsa-sha2-nistp256" | | ||
190 | "ecdsa-sha2-nistp384" | | ||
191 | "ecdsa-sha2-nistp521" | ||
192 | string ecdsa_curve_name | ||
193 | string ecdsa_public_key | ||
194 | mpint ecdsa_private | ||
195 | string key_comment | ||
196 | constraint[] key_constraints | ||
197 | |||
198 | ECDSA certificates may be added with: | ||
199 | byte SSH2_AGENTC_ADD_IDENTITY or | ||
200 | SSH2_AGENTC_ADD_ID_CONSTRAINED | ||
201 | string "ecdsa-sha2-nistp256-cert-v01@openssh.com" | | ||
202 | "ecdsa-sha2-nistp384-cert-v01@openssh.com" | | ||
203 | "ecdsa-sha2-nistp521-cert-v01@openssh.com" | ||
204 | string certificate | ||
205 | mpint ecdsa_private_key | ||
206 | string key_comment | ||
207 | constraint[] key_constraints | ||
208 | |||
185 | RSA keys may be added with this request: | 209 | RSA keys may be added with this request: |
186 | 210 | ||
187 | byte SSH2_AGENTC_ADD_IDENTITY or | 211 | byte SSH2_AGENTC_ADD_IDENTITY or |
@@ -214,7 +238,7 @@ order to the protocol 1 add keys message. As with the corresponding | |||
214 | protocol 1 "add key" request, the private key is overspecified to avoid | 238 | protocol 1 "add key" request, the private key is overspecified to avoid |
215 | redundant processing. | 239 | redundant processing. |
216 | 240 | ||
217 | For both DSA and RSA key add requests, "key_constraints" may only be | 241 | For DSA, ECDSA and RSA key add requests, "key_constraints" may only be |
218 | present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED. | 242 | present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED. |
219 | 243 | ||
220 | The agent will reply with a SSH_AGENT_SUCCESS if the key has been | 244 | The agent will reply with a SSH_AGENT_SUCCESS if the key has been |
@@ -294,8 +318,7 @@ Protocol 2 keys may be removed with the following request: | |||
294 | string key_blob | 318 | string key_blob |
295 | 319 | ||
296 | Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key | 320 | Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key |
297 | Algorithms" for either of the supported key types: "ssh-dss" or | 321 | Algorithms" for any of the supported protocol 2 key types. |
298 | "ssh-rsa". | ||
299 | 322 | ||
300 | The agent will delete any private key matching the specified public key | 323 | The agent will delete any private key matching the specified public key |
301 | and return SSH_AGENT_SUCCESS. If no such key was found, the agent will | 324 | and return SSH_AGENT_SUCCESS. If no such key was found, the agent will |
@@ -364,8 +387,7 @@ Followed by zero or more consecutive keys, encoded as: | |||
364 | string key_comment | 387 | string key_comment |
365 | 388 | ||
366 | Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key | 389 | Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key |
367 | Algorithms" for either of the supported key types: "ssh-dss" or | 390 | Algorithms" for any of the supported protocol 2 key types. |
368 | "ssh-rsa". | ||
369 | 391 | ||
370 | 2.6 Private key operations | 392 | 2.6 Private key operations |
371 | 393 | ||
@@ -429,9 +451,9 @@ a protocol 2 key: | |||
429 | uint32 flags | 451 | uint32 flags |
430 | 452 | ||
431 | Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key | 453 | Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key |
432 | Algorithms" for either of the supported key types: "ssh-dss" or | 454 | Algorithms" for any of the supported protocol 2 key types. "flags" is |
433 | "ssh-rsa". "flags" is a bit-mask, but at present only one possible value | 455 | a bit-mask, but at present only one possible value is defined (see below |
434 | is defined (see below for its meaning): | 456 | for its meaning): |
435 | 457 | ||
436 | SSH_AGENT_OLD_SIGNATURE 1 | 458 | SSH_AGENT_OLD_SIGNATURE 1 |
437 | 459 | ||
@@ -535,4 +557,4 @@ Locking and unlocking affects both protocol 1 and protocol 2 keys. | |||
535 | SSH_AGENT_CONSTRAIN_LIFETIME 1 | 557 | SSH_AGENT_CONSTRAIN_LIFETIME 1 |
536 | SSH_AGENT_CONSTRAIN_CONFIRM 2 | 558 | SSH_AGENT_CONSTRAIN_CONFIRM 2 |
537 | 559 | ||
538 | $OpenBSD: PROTOCOL.agent,v 1.5 2010/02/26 20:29:54 djm Exp $ | 560 | $OpenBSD: PROTOCOL.agent,v 1.6 2010/08/31 11:54:45 djm Exp $ |
diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys index 1d1be13da..2f9764981 100644 --- a/PROTOCOL.certkeys +++ b/PROTOCOL.certkeys | |||
@@ -5,31 +5,37 @@ Background | |||
5 | ---------- | 5 | ---------- |
6 | 6 | ||
7 | The SSH protocol currently supports a simple public key authentication | 7 | The SSH protocol currently supports a simple public key authentication |
8 | mechanism. Unlike other public key implementations, SSH eschews the | 8 | mechanism. Unlike other public key implementations, SSH eschews the use |
9 | use of X.509 certificates and uses raw keys. This approach has some | 9 | of X.509 certificates and uses raw keys. This approach has some benefits |
10 | benefits relating to simplicity of configuration and minimisation | 10 | relating to simplicity of configuration and minimisation of attack |
11 | of attack surface, but it does not support the important use-cases | 11 | surface, but it does not support the important use-cases of centrally |
12 | of centrally managed, passwordless authentication and centrally | 12 | managed, passwordless authentication and centrally certified host keys. |
13 | certified host keys. | ||
14 | 13 | ||
15 | These protocol extensions build on the simple public key authentication | 14 | These protocol extensions build on the simple public key authentication |
16 | system already in SSH to allow certificate-based authentication. | 15 | system already in SSH to allow certificate-based authentication. The |
17 | The certificates used are not traditional X.509 certificates, with | 16 | certificates used are not traditional X.509 certificates, with numerous |
18 | numerous options and complex encoding rules, but something rather | 17 | options and complex encoding rules, but something rather more minimal: a |
19 | more minimal: a key, some identity information and usage options | 18 | key, some identity information and usage options that have been signed |
20 | that have been signed with some other trusted key. | 19 | with some other trusted key. |
21 | 20 | ||
22 | A sshd server may be configured to allow authentication via certified | 21 | A sshd server may be configured to allow authentication via certified |
23 | keys, by extending the existing ~/.ssh/authorized_keys mechanism | 22 | keys, by extending the existing ~/.ssh/authorized_keys mechanism to |
24 | to allow specification of certification authority keys in addition | 23 | allow specification of certification authority keys in addition to |
25 | to raw user keys. The ssh client will support automatic verification | 24 | raw user keys. The ssh client will support automatic verification of |
26 | of acceptance of certified host keys, by adding a similar ability | 25 | acceptance of certified host keys, by adding a similar ability to |
27 | to specify CA keys in ~/.ssh/known_hosts. | 26 | specify CA keys in ~/.ssh/known_hosts. |
28 | 27 | ||
29 | Certified keys are represented using two new key types: | 28 | Certified keys are represented using new key types: |
30 | ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that | 29 | |
31 | include certification information along with the public key that is used | 30 | ssh-rsa-cert-v01@openssh.com |
32 | to sign challenges. ssh-keygen performs the CA signing operation. | 31 | ssh-dss-cert-v01@openssh.com |
32 | ecdsa-sha2-nistp256-cert-v01@openssh.com | ||
33 | ecdsa-sha2-nistp384-cert-v01@openssh.com | ||
34 | ecdsa-sha2-nistp521-cert-v01@openssh.com | ||
35 | |||
36 | These include certification information along with the public key | ||
37 | that is used to sign challenges. ssh-keygen performs the CA signing | ||
38 | operation. | ||
33 | 39 | ||
34 | Protocol extensions | 40 | Protocol extensions |
35 | ------------------- | 41 | ------------------- |
@@ -47,10 +53,9 @@ in RFC4252 section 7. | |||
47 | New public key formats | 53 | New public key formats |
48 | ---------------------- | 54 | ---------------------- |
49 | 55 | ||
50 | The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key | 56 | The certificate key types take a similar high-level format (note: data |
51 | types take a similar high-level format (note: data types and | 57 | types and encoding are as per RFC4251 section 5). The serialised wire |
52 | encoding are as per RFC4251 section 5). The serialised wire encoding of | 58 | encoding of these certificates is also used for storing them on disk. |
53 | these certificates is also used for storing them on disk. | ||
54 | 59 | ||
55 | #define SSH_CERT_TYPE_USER 1 | 60 | #define SSH_CERT_TYPE_USER 1 |
56 | #define SSH_CERT_TYPE_HOST 2 | 61 | #define SSH_CERT_TYPE_HOST 2 |
@@ -93,6 +98,26 @@ DSA certificate | |||
93 | string signature key | 98 | string signature key |
94 | string signature | 99 | string signature |
95 | 100 | ||
101 | ECDSA certificate | ||
102 | |||
103 | string "ecdsa-sha2-nistp256@openssh.com" | | ||
104 | "ecdsa-sha2-nistp384@openssh.com" | | ||
105 | "ecdsa-sha2-nistp521@openssh.com" | ||
106 | string nonce | ||
107 | string curve | ||
108 | string public_key | ||
109 | uint64 serial | ||
110 | uint32 type | ||
111 | string key id | ||
112 | string valid principals | ||
113 | uint64 valid after | ||
114 | uint64 valid before | ||
115 | string critical options | ||
116 | string extensions | ||
117 | string reserved | ||
118 | string signature key | ||
119 | string signature | ||
120 | |||
96 | The nonce field is a CA-provided random bitstring of arbitrary length | 121 | The nonce field is a CA-provided random bitstring of arbitrary length |
97 | (but typically 16 or 32 bytes) included to make attacks that depend on | 122 | (but typically 16 or 32 bytes) included to make attacks that depend on |
98 | inducing collisions in the signature hash infeasible. | 123 | inducing collisions in the signature hash infeasible. |
@@ -101,6 +126,9 @@ e and n are the RSA exponent and public modulus respectively. | |||
101 | 126 | ||
102 | p, q, g, y are the DSA parameters as described in FIPS-186-2. | 127 | p, q, g, y are the DSA parameters as described in FIPS-186-2. |
103 | 128 | ||
129 | curve and public key are respectively the ECDSA "[identifier]" and "Q" | ||
130 | defined in section 3.1 of RFC5656. | ||
131 | |||
104 | serial is an optional certificate serial number set by the CA to | 132 | serial is an optional certificate serial number set by the CA to |
105 | provide an abbreviated way to refer to certificates from that CA. | 133 | provide an abbreviated way to refer to certificates from that CA. |
106 | If a CA does not wish to number its certificates it must set this | 134 | If a CA does not wish to number its certificates it must set this |
@@ -123,7 +151,8 @@ any principal of the specified type. XXX DNS wildcards? | |||
123 | "valid after" and "valid before" specify a validity period for the | 151 | "valid after" and "valid before" specify a validity period for the |
124 | certificate. Each represents a time in seconds since 1970-01-01 | 152 | certificate. Each represents a time in seconds since 1970-01-01 |
125 | 00:00:00. A certificate is considered valid if: | 153 | 00:00:00. A certificate is considered valid if: |
126 | valid after <= current time < valid before | 154 | |
155 | valid after <= current time < valid before | ||
127 | 156 | ||
128 | criticial options is a set of zero or more key options encoded as | 157 | criticial options is a set of zero or more key options encoded as |
129 | below. All such options are "critical" in the sense that an implementation | 158 | below. All such options are "critical" in the sense that an implementation |
@@ -137,15 +166,17 @@ The reserved field is currently unused and is ignored in this version of | |||
137 | the protocol. | 166 | the protocol. |
138 | 167 | ||
139 | signature key contains the CA key used to sign the certificate. | 168 | signature key contains the CA key used to sign the certificate. |
140 | The valid key types for CA keys are ssh-rsa and ssh-dss. "Chained" | 169 | The valid key types for CA keys are ssh-rsa, ssh-dss and the ECDSA types |
170 | ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained" | ||
141 | certificates, where the signature key type is a certificate type itself | 171 | certificates, where the signature key type is a certificate type itself |
142 | are NOT supported. Note that it is possible for a RSA certificate key to | 172 | are NOT supported. Note that it is possible for a RSA certificate key to |
143 | be signed by a DSS CA key and vice-versa. | 173 | be signed by a DSS or ECDSA CA key and vice-versa. |
144 | 174 | ||
145 | signature is computed over all preceding fields from the initial string | 175 | signature is computed over all preceding fields from the initial string |
146 | up to, and including the signature key. Signatures are computed and | 176 | up to, and including the signature key. Signatures are computed and |
147 | encoded according to the rules defined for the CA's public key algorithm | 177 | encoded according to the rules defined for the CA's public key algorithm |
148 | (RFC4253 section 6.6 for ssh-rsa and ssh-dss). | 178 | (RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA |
179 | types). | ||
149 | 180 | ||
150 | Critical options | 181 | Critical options |
151 | ---------------- | 182 | ---------------- |
@@ -222,4 +253,4 @@ permit-user-rc empty Flag indicating that execution of | |||
222 | of this script will not be permitted if | 253 | of this script will not be permitted if |
223 | this option is not present. | 254 | this option is not present. |
224 | 255 | ||
225 | $OpenBSD: PROTOCOL.certkeys,v 1.7 2010/08/04 05:40:39 djm Exp $ | 256 | $OpenBSD: PROTOCOL.certkeys,v 1.8 2010/08/31 11:54:45 djm Exp $ |
diff --git a/auth2-jpake.c b/auth2-jpake.c index 5de5506a6..a460e8216 100644 --- a/auth2-jpake.c +++ b/auth2-jpake.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2-jpake.c,v 1.3 2009/03/05 07:18:19 djm Exp $ */ | 1 | /* $OpenBSD: auth2-jpake.c,v 1.4 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 3 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
4 | * | 4 | * |
@@ -162,6 +162,11 @@ derive_rawsalt(const char *username, u_char *rawsalt, u_int len) | |||
162 | fatal("%s: DSA key missing priv_key", __func__); | 162 | fatal("%s: DSA key missing priv_key", __func__); |
163 | buffer_put_bignum2(&b, k->dsa->priv_key); | 163 | buffer_put_bignum2(&b, k->dsa->priv_key); |
164 | break; | 164 | break; |
165 | case KEY_ECDSA: | ||
166 | if (EC_KEY_get0_private_key(k->ecdsa) == NULL) | ||
167 | fatal("%s: ECDSA key missing priv_key", __func__); | ||
168 | buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa)); | ||
169 | break; | ||
165 | default: | 170 | default: |
166 | fatal("%s: unknown key type %d", __func__, k->type); | 171 | fatal("%s: unknown key type %d", __func__, k->type); |
167 | } | 172 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfd.c,v 1.83 2010/04/16 01:47:26 djm Exp $ */ | 1 | /* $OpenBSD: authfd.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -509,6 +509,19 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) | |||
509 | buffer_len(&key->cert->certblob)); | 509 | buffer_len(&key->cert->certblob)); |
510 | buffer_put_bignum2(b, key->dsa->priv_key); | 510 | buffer_put_bignum2(b, key->dsa->priv_key); |
511 | break; | 511 | break; |
512 | case KEY_ECDSA: | ||
513 | buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid)); | ||
514 | buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa), | ||
515 | EC_KEY_get0_public_key(key->ecdsa)); | ||
516 | buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); | ||
517 | break; | ||
518 | case KEY_ECDSA_CERT: | ||
519 | if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) | ||
520 | fatal("%s: no cert/certblob", __func__); | ||
521 | buffer_put_string(b, buffer_ptr(&key->cert->certblob), | ||
522 | buffer_len(&key->cert->certblob)); | ||
523 | buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); | ||
524 | break; | ||
512 | } | 525 | } |
513 | buffer_put_cstring(b, comment); | 526 | buffer_put_cstring(b, comment); |
514 | } | 527 | } |
@@ -541,6 +554,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, | |||
541 | case KEY_DSA: | 554 | case KEY_DSA: |
542 | case KEY_DSA_CERT: | 555 | case KEY_DSA_CERT: |
543 | case KEY_DSA_CERT_V00: | 556 | case KEY_DSA_CERT_V00: |
557 | case KEY_ECDSA: | ||
558 | case KEY_ECDSA_CERT: | ||
544 | type = constrained ? | 559 | type = constrained ? |
545 | SSH2_AGENTC_ADD_ID_CONSTRAINED : | 560 | SSH2_AGENTC_ADD_ID_CONSTRAINED : |
546 | SSH2_AGENTC_ADD_IDENTITY; | 561 | SSH2_AGENTC_ADD_IDENTITY; |
@@ -589,7 +604,8 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key) | |||
589 | buffer_put_bignum(&msg, key->rsa->e); | 604 | buffer_put_bignum(&msg, key->rsa->e); |
590 | buffer_put_bignum(&msg, key->rsa->n); | 605 | buffer_put_bignum(&msg, key->rsa->n); |
591 | } else if (key_type_plain(key->type) == KEY_DSA || | 606 | } else if (key_type_plain(key->type) == KEY_DSA || |
592 | key_type_plain(key->type) == KEY_RSA) { | 607 | key_type_plain(key->type) == KEY_RSA || |
608 | key_type_plain(key->type) == KEY_ECDSA) { | ||
593 | key_to_blob(key, &blob, &blen); | 609 | key_to_blob(key, &blob, &blen); |
594 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); | 610 | buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); |
595 | buffer_put_string(&msg, blob, blen); | 611 | buffer_put_string(&msg, blob, blen); |
diff --git a/authfile.c b/authfile.c index 2bd887845..865e7faf9 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.82 2010/08/04 05:49:22 djm Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.83 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -213,6 +213,10 @@ key_save_private_pem(Key *key, const char *filename, const char *_passphrase, | |||
213 | success = PEM_write_DSAPrivateKey(fp, key->dsa, | 213 | success = PEM_write_DSAPrivateKey(fp, key->dsa, |
214 | cipher, passphrase, len, NULL, NULL); | 214 | cipher, passphrase, len, NULL, NULL); |
215 | break; | 215 | break; |
216 | case KEY_ECDSA: | ||
217 | success = PEM_write_ECPrivateKey(fp, key->ecdsa, | ||
218 | cipher, passphrase, len, NULL, NULL); | ||
219 | break; | ||
216 | case KEY_RSA: | 220 | case KEY_RSA: |
217 | success = PEM_write_RSAPrivateKey(fp, key->rsa, | 221 | success = PEM_write_RSAPrivateKey(fp, key->rsa, |
218 | cipher, passphrase, len, NULL, NULL); | 222 | cipher, passphrase, len, NULL, NULL); |
@@ -231,6 +235,7 @@ key_save_private(Key *key, const char *filename, const char *passphrase, | |||
231 | return key_save_private_rsa1(key, filename, passphrase, | 235 | return key_save_private_rsa1(key, filename, passphrase, |
232 | comment); | 236 | comment); |
233 | case KEY_DSA: | 237 | case KEY_DSA: |
238 | case KEY_ECDSA: | ||
234 | case KEY_RSA: | 239 | case KEY_RSA: |
235 | return key_save_private_pem(key, filename, passphrase, | 240 | return key_save_private_pem(key, filename, passphrase, |
236 | comment); | 241 | comment); |
@@ -510,6 +515,29 @@ key_load_private_pem(int fd, int type, const char *passphrase, | |||
510 | #ifdef DEBUG_PK | 515 | #ifdef DEBUG_PK |
511 | DSA_print_fp(stderr, prv->dsa, 8); | 516 | DSA_print_fp(stderr, prv->dsa, 8); |
512 | #endif | 517 | #endif |
518 | } else if (pk->type == EVP_PKEY_EC && | ||
519 | (type == KEY_UNSPEC||type==KEY_ECDSA)) { | ||
520 | prv = key_new(KEY_UNSPEC); | ||
521 | prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); | ||
522 | prv->type = KEY_ECDSA; | ||
523 | prv->ecdsa_nid = key_ecdsa_group_to_nid( | ||
524 | EC_KEY_get0_group(prv->ecdsa)); | ||
525 | if (key_curve_nid_to_name(prv->ecdsa_nid) == NULL) { | ||
526 | key_free(prv); | ||
527 | prv = NULL; | ||
528 | } | ||
529 | if (key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), | ||
530 | EC_KEY_get0_public_key(prv->ecdsa)) != 0 || | ||
531 | key_ec_validate_private(prv->ecdsa) != 0) { | ||
532 | error("%s: bad ECDSA key", __func__); | ||
533 | key_free(prv); | ||
534 | prv = NULL; | ||
535 | } | ||
536 | name = "dsa w/o comment"; | ||
537 | #ifdef DEBUG_PK | ||
538 | if (prv->ecdsa != NULL) | ||
539 | key_dump_ec_key(prv->ecdsa); | ||
540 | #endif | ||
513 | } else { | 541 | } else { |
514 | error("PEM_read_PrivateKey: mismatch or " | 542 | error("PEM_read_PrivateKey: mismatch or " |
515 | "unknown EVP_PKEY save_type %d", pk->save_type); | 543 | "unknown EVP_PKEY save_type %d", pk->save_type); |
@@ -581,6 +609,7 @@ key_load_private_type(int type, const char *filename, const char *passphrase, | |||
581 | commentp); | 609 | commentp); |
582 | /* closes fd */ | 610 | /* closes fd */ |
583 | case KEY_DSA: | 611 | case KEY_DSA: |
612 | case KEY_ECDSA: | ||
584 | case KEY_RSA: | 613 | case KEY_RSA: |
585 | case KEY_UNSPEC: | 614 | case KEY_UNSPEC: |
586 | return key_load_private_pem(fd, type, passphrase, commentp); | 615 | return key_load_private_pem(fd, type, passphrase, commentp); |
@@ -721,6 +750,7 @@ key_load_private_cert(int type, const char *filename, const char *passphrase, | |||
721 | switch (type) { | 750 | switch (type) { |
722 | case KEY_RSA: | 751 | case KEY_RSA: |
723 | case KEY_DSA: | 752 | case KEY_DSA: |
753 | case KEY_ECDSA: | ||
724 | break; | 754 | break; |
725 | default: | 755 | default: |
726 | error("%s: unsupported key type", __func__); | 756 | error("%s: unsupported key type", __func__); |
diff --git a/bufec.c b/bufec.c new file mode 100644 index 000000000..dff9c69c9 --- /dev/null +++ b/bufec.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /* $OpenBSD: bufec.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2010 Damien Miller <djm@mindrot.org> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | #include <sys/types.h> | ||
18 | |||
19 | #include <openssl/bn.h> | ||
20 | #include <openssl/ec.h> | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <stdarg.h> | ||
24 | |||
25 | #include "xmalloc.h" | ||
26 | #include "buffer.h" | ||
27 | #include "log.h" | ||
28 | #include "misc.h" | ||
29 | |||
30 | /* | ||
31 | * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed | ||
32 | * encoding represents this as two bitstring points that should each | ||
33 | * be no longer than the field length, SEC1 specifies a 1 byte | ||
34 | * point type header. | ||
35 | * Being paranoid here may insulate us to parsing problems in | ||
36 | * EC_POINT_oct2point. | ||
37 | */ | ||
38 | #define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1) | ||
39 | |||
40 | /* | ||
41 | * Append an EC_POINT to the buffer as a string containing a SEC1 encoded | ||
42 | * uncompressed point. Fortunately OpenSSL handles the gory details for us. | ||
43 | */ | ||
44 | int | ||
45 | buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, | ||
46 | const EC_POINT *point) | ||
47 | { | ||
48 | u_char *buf = NULL; | ||
49 | size_t len; | ||
50 | BN_CTX *bnctx; | ||
51 | int ret = -1; | ||
52 | |||
53 | /* Determine length */ | ||
54 | if ((bnctx = BN_CTX_new()) == NULL) | ||
55 | fatal("%s: BN_CTX_new failed", __func__); | ||
56 | len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, | ||
57 | NULL, 0, bnctx); | ||
58 | if (len > BUFFER_MAX_ECPOINT_LEN) { | ||
59 | error("%s: giant EC point: len = %lu (max %u)", | ||
60 | __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN); | ||
61 | goto out; | ||
62 | } | ||
63 | /* Convert */ | ||
64 | buf = xmalloc(len); | ||
65 | if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, | ||
66 | buf, len, bnctx) != len) { | ||
67 | error("%s: EC_POINT_point2oct length mismatch", __func__); | ||
68 | goto out; | ||
69 | } | ||
70 | /* Append */ | ||
71 | buffer_put_string(buffer, buf, len); | ||
72 | ret = 0; | ||
73 | out: | ||
74 | if (buf != NULL) { | ||
75 | bzero(buf, len); | ||
76 | xfree(buf); | ||
77 | } | ||
78 | BN_CTX_free(bnctx); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | void | ||
83 | buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve, | ||
84 | const EC_POINT *point) | ||
85 | { | ||
86 | if (buffer_put_ecpoint_ret(buffer, curve, point) == -1) | ||
87 | fatal("%s: buffer error", __func__); | ||
88 | } | ||
89 | |||
90 | int | ||
91 | buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, | ||
92 | EC_POINT *point) | ||
93 | { | ||
94 | u_char *buf; | ||
95 | u_int len; | ||
96 | BN_CTX *bnctx; | ||
97 | int ret = -1; | ||
98 | |||
99 | if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) { | ||
100 | error("%s: invalid point", __func__); | ||
101 | return -1; | ||
102 | } | ||
103 | if ((bnctx = BN_CTX_new()) == NULL) | ||
104 | fatal("%s: BN_CTX_new failed", __func__); | ||
105 | if (len > BUFFER_MAX_ECPOINT_LEN) { | ||
106 | error("%s: EC_POINT too long: %u > max %u", __func__, | ||
107 | len, BUFFER_MAX_ECPOINT_LEN); | ||
108 | goto out; | ||
109 | } | ||
110 | if (len == 0) { | ||
111 | error("%s: EC_POINT buffer is empty", __func__); | ||
112 | goto out; | ||
113 | } | ||
114 | if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) { | ||
115 | error("%s: EC_POINT is in an incorrect form: " | ||
116 | "0x%02x (want 0x%02x)", __func__, buf[0], | ||
117 | POINT_CONVERSION_UNCOMPRESSED); | ||
118 | goto out; | ||
119 | } | ||
120 | if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) { | ||
121 | error("buffer_get_bignum2_ret: BN_bin2bn failed"); | ||
122 | goto out; | ||
123 | } | ||
124 | /* EC_POINT_oct2point verifies that the point is on the curve for us */ | ||
125 | ret = 0; | ||
126 | out: | ||
127 | BN_CTX_free(bnctx); | ||
128 | bzero(buf, len); | ||
129 | xfree(buf); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | void | ||
134 | buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve, | ||
135 | EC_POINT *point) | ||
136 | { | ||
137 | if (buffer_get_ecpoint_ret(buffer, curve, point) == -1) | ||
138 | fatal("%s: buffer error", __func__); | ||
139 | } | ||
140 | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: buffer.h,v 1.20 2010/08/31 09:58:37 djm Exp $ */ | 1 | /* $OpenBSD: buffer.h,v 1.21 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -86,4 +86,11 @@ char *buffer_get_cstring_ret(Buffer *, u_int *); | |||
86 | void *buffer_get_string_ptr_ret(Buffer *, u_int *); | 86 | void *buffer_get_string_ptr_ret(Buffer *, u_int *); |
87 | int buffer_get_char_ret(char *, Buffer *); | 87 | int buffer_get_char_ret(char *, Buffer *); |
88 | 88 | ||
89 | #include <openssl/ec.h> | ||
90 | |||
91 | int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *); | ||
92 | void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *); | ||
93 | int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *); | ||
94 | void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *); | ||
95 | |||
89 | #endif /* BUFFER_H */ | 96 | #endif /* BUFFER_H */ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dns.c,v 1.26 2010/02/26 20:29:54 djm Exp $ */ | 1 | /* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2003 Wesley Griffin. All rights reserved. | 4 | * Copyright (c) 2003 Wesley Griffin. All rights reserved. |
@@ -86,6 +86,7 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type, | |||
86 | case KEY_DSA: | 86 | case KEY_DSA: |
87 | *algorithm = SSHFP_KEY_DSA; | 87 | *algorithm = SSHFP_KEY_DSA; |
88 | break; | 88 | break; |
89 | /* XXX KEY_ECDSA */ | ||
89 | default: | 90 | default: |
90 | *algorithm = SSHFP_KEY_RESERVED; /* 0 */ | 91 | *algorithm = SSHFP_KEY_RESERVED; /* 0 */ |
91 | } | 92 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.83 2010/08/31 09:58:37 djm Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -325,6 +325,10 @@ choose_kex(Kex *k, char *client, char *server) | |||
325 | } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { | 325 | } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { |
326 | k->kex_type = KEX_DH_GEX_SHA256; | 326 | k->kex_type = KEX_DH_GEX_SHA256; |
327 | k->evp_md = evp_ssh_sha256(); | 327 | k->evp_md = evp_ssh_sha256(); |
328 | } else if (strncmp(k->name, KEX_ECDH_SHA256, | ||
329 | sizeof(KEX_ECDH_SHA256) - 1) == 0) { | ||
330 | k->kex_type = KEX_ECDH_SHA2; | ||
331 | k->evp_md = evp_ssh_sha256(); | ||
328 | #endif | 332 | #endif |
329 | } else | 333 | } else |
330 | fatal("bad kex alg %s", k->name); | 334 | fatal("bad kex alg %s", k->name); |
@@ -559,11 +563,11 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, | |||
559 | memset(&md, 0, sizeof(md)); | 563 | memset(&md, 0, sizeof(md)); |
560 | } | 564 | } |
561 | 565 | ||
562 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) | 566 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) |
563 | void | 567 | void |
564 | dump_digest(char *msg, u_char *digest, int len) | 568 | dump_digest(char *msg, u_char *digest, int len) |
565 | { | 569 | { |
566 | u_int i; | 570 | int i; |
567 | 571 | ||
568 | fprintf(stderr, "%s\n", msg); | 572 | fprintf(stderr, "%s\n", msg); |
569 | for (i = 0; i < len; i++) { | 573 | for (i = 0; i < len; i++) { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.49 2010/02/26 20:29:54 djm Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.50 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -29,6 +29,7 @@ | |||
29 | #include <signal.h> | 29 | #include <signal.h> |
30 | #include <openssl/evp.h> | 30 | #include <openssl/evp.h> |
31 | #include <openssl/hmac.h> | 31 | #include <openssl/hmac.h> |
32 | #include <openssl/ec.h> | ||
32 | 33 | ||
33 | #define KEX_COOKIE_LEN 16 | 34 | #define KEX_COOKIE_LEN 16 |
34 | 35 | ||
@@ -37,6 +38,8 @@ | |||
37 | #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" | 38 | #define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1" |
38 | #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" | 39 | #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" |
39 | #define KEX_RESUME "resume@appgate.com" | 40 | #define KEX_RESUME "resume@appgate.com" |
41 | /* The following represents the family of ECDH methods */ | ||
42 | #define KEX_ECDH_SHA256 "ecdh-sha2-" | ||
40 | 43 | ||
41 | #define COMP_NONE 0 | 44 | #define COMP_NONE 0 |
42 | #define COMP_ZLIB 1 | 45 | #define COMP_ZLIB 1 |
@@ -67,6 +70,7 @@ enum kex_exchange { | |||
67 | KEX_DH_GRP14_SHA1, | 70 | KEX_DH_GRP14_SHA1, |
68 | KEX_DH_GEX_SHA1, | 71 | KEX_DH_GEX_SHA1, |
69 | KEX_DH_GEX_SHA256, | 72 | KEX_DH_GEX_SHA256, |
73 | KEX_ECDH_SHA2, | ||
70 | KEX_MAX | 74 | KEX_MAX |
71 | }; | 75 | }; |
72 | 76 | ||
@@ -145,6 +149,8 @@ void kexdh_client(Kex *); | |||
145 | void kexdh_server(Kex *); | 149 | void kexdh_server(Kex *); |
146 | void kexgex_client(Kex *); | 150 | void kexgex_client(Kex *); |
147 | void kexgex_server(Kex *); | 151 | void kexgex_server(Kex *); |
152 | void kexecdh_client(Kex *); | ||
153 | void kexecdh_server(Kex *); | ||
148 | 154 | ||
149 | void | 155 | void |
150 | kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, | 156 | kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, |
@@ -153,11 +159,17 @@ void | |||
153 | kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *, | 159 | kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *, |
154 | int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, | 160 | int, u_char *, int, int, int, int, BIGNUM *, BIGNUM *, BIGNUM *, |
155 | BIGNUM *, BIGNUM *, u_char **, u_int *); | 161 | BIGNUM *, BIGNUM *, u_char **, u_int *); |
162 | void | ||
163 | kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int, | ||
164 | char *, int, u_char *, int, const EC_POINT *, const EC_POINT *, | ||
165 | const BIGNUM *, u_char **, u_int *); | ||
166 | |||
167 | int kex_ecdh_name_to_nid(const char *); | ||
156 | 168 | ||
157 | void | 169 | void |
158 | derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); | 170 | derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); |
159 | 171 | ||
160 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) | 172 | #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) |
161 | void dump_digest(char *, u_char *, int); | 173 | void dump_digest(char *, u_char *, int); |
162 | #endif | 174 | #endif |
163 | 175 | ||
diff --git a/kexecdh.c b/kexecdh.c new file mode 100644 index 000000000..a5a14f4bd --- /dev/null +++ b/kexecdh.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* $OpenBSD: kexecdh.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | ||
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | #include <sys/types.h> | ||
28 | |||
29 | #include <signal.h> | ||
30 | #include <string.h> | ||
31 | |||
32 | #include <openssl/bn.h> | ||
33 | #include <openssl/evp.h> | ||
34 | #include <openssl/ec.h> | ||
35 | #include <openssl/ecdh.h> | ||
36 | |||
37 | #include "buffer.h" | ||
38 | #include "ssh2.h" | ||
39 | #include "key.h" | ||
40 | #include "cipher.h" | ||
41 | #include "kex.h" | ||
42 | #include "log.h" | ||
43 | |||
44 | int | ||
45 | kex_ecdh_name_to_nid(const char *kexname) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | if (strlen(kexname) < sizeof(KEX_ECDH_SHA256) - 1) | ||
50 | fatal("%s: kexname too short \"%s\"", __func__, kexname); | ||
51 | ret = key_curve_name_to_nid(kexname + sizeof(KEX_ECDH_SHA256) - 1); | ||
52 | if (ret == -1) | ||
53 | fatal("%s: unsupported curve negotiated \"%s\"", __func__, | ||
54 | kexname); | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | kex_ecdh_hash( | ||
60 | const EVP_MD *evp_md, | ||
61 | const EC_GROUP *ec_group, | ||
62 | char *client_version_string, | ||
63 | char *server_version_string, | ||
64 | char *ckexinit, int ckexinitlen, | ||
65 | char *skexinit, int skexinitlen, | ||
66 | u_char *serverhostkeyblob, int sbloblen, | ||
67 | const EC_POINT *client_dh_pub, | ||
68 | const EC_POINT *server_dh_pub, | ||
69 | const BIGNUM *shared_secret, | ||
70 | u_char **hash, u_int *hashlen) | ||
71 | { | ||
72 | Buffer b; | ||
73 | EVP_MD_CTX md; | ||
74 | static u_char digest[EVP_MAX_MD_SIZE]; | ||
75 | |||
76 | buffer_init(&b); | ||
77 | buffer_put_cstring(&b, client_version_string); | ||
78 | buffer_put_cstring(&b, server_version_string); | ||
79 | |||
80 | /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ | ||
81 | buffer_put_int(&b, ckexinitlen+1); | ||
82 | buffer_put_char(&b, SSH2_MSG_KEXINIT); | ||
83 | buffer_append(&b, ckexinit, ckexinitlen); | ||
84 | buffer_put_int(&b, skexinitlen+1); | ||
85 | buffer_put_char(&b, SSH2_MSG_KEXINIT); | ||
86 | buffer_append(&b, skexinit, skexinitlen); | ||
87 | |||
88 | buffer_put_string(&b, serverhostkeyblob, sbloblen); | ||
89 | buffer_put_ecpoint(&b, ec_group, client_dh_pub); | ||
90 | buffer_put_ecpoint(&b, ec_group, server_dh_pub); | ||
91 | buffer_put_bignum2(&b, shared_secret); | ||
92 | |||
93 | #ifdef DEBUG_KEX | ||
94 | buffer_dump(&b); | ||
95 | #endif | ||
96 | EVP_DigestInit(&md, evp_md); | ||
97 | EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b)); | ||
98 | EVP_DigestFinal(&md, digest, NULL); | ||
99 | |||
100 | buffer_free(&b); | ||
101 | |||
102 | #ifdef DEBUG_KEX | ||
103 | dump_digest("hash", digest, EVP_MD_size(evp_md)); | ||
104 | #endif | ||
105 | *hash = digest; | ||
106 | *hashlen = EVP_MD_size(evp_md); | ||
107 | } | ||
108 | |||
diff --git a/kexecdhc.c b/kexecdhc.c new file mode 100644 index 000000000..f6d9977c5 --- /dev/null +++ b/kexecdhc.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* $OpenBSD: kexecdhc.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | ||
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | #include <sys/types.h> | ||
28 | |||
29 | #include <stdio.h> | ||
30 | #include <string.h> | ||
31 | #include <signal.h> | ||
32 | |||
33 | #include <openssl/ecdh.h> | ||
34 | |||
35 | #include "xmalloc.h" | ||
36 | #include "buffer.h" | ||
37 | #include "key.h" | ||
38 | #include "cipher.h" | ||
39 | #include "kex.h" | ||
40 | #include "log.h" | ||
41 | #include "packet.h" | ||
42 | #include "dh.h" | ||
43 | #include "ssh2.h" | ||
44 | |||
45 | void | ||
46 | kexecdh_client(Kex *kex) | ||
47 | { | ||
48 | EC_KEY *client_key; | ||
49 | EC_POINT *server_public; | ||
50 | const EC_GROUP *group; | ||
51 | BIGNUM *shared_secret; | ||
52 | Key *server_host_key; | ||
53 | u_char *server_host_key_blob = NULL, *signature = NULL; | ||
54 | u_char *kbuf, *hash; | ||
55 | u_int klen, slen, sbloblen, hashlen; | ||
56 | int curve_nid; | ||
57 | |||
58 | curve_nid = kex_ecdh_name_to_nid(kex->name); | ||
59 | if ((client_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL) | ||
60 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | ||
61 | if (EC_KEY_generate_key(client_key) != 1) | ||
62 | fatal("%s: EC_KEY_generate_key failed", __func__); | ||
63 | group = EC_KEY_get0_group(client_key); | ||
64 | |||
65 | packet_start(SSH2_MSG_KEX_ECDH_INIT); | ||
66 | packet_put_ecpoint(group, EC_KEY_get0_public_key(client_key)); | ||
67 | packet_send(); | ||
68 | debug("sending SSH2_MSG_KEX_ECDH_INIT"); | ||
69 | |||
70 | #ifdef DEBUG_KEXECDH | ||
71 | fputs("client private key:\n", stderr); | ||
72 | key_dump_ec_key(client_key); | ||
73 | #endif | ||
74 | |||
75 | debug("expecting SSH2_MSG_KEX_ECDH_REPLY"); | ||
76 | packet_read_expect(SSH2_MSG_KEX_ECDH_REPLY); | ||
77 | |||
78 | /* hostkey */ | ||
79 | server_host_key_blob = packet_get_string(&sbloblen); | ||
80 | server_host_key = key_from_blob(server_host_key_blob, sbloblen); | ||
81 | if (server_host_key == NULL) | ||
82 | fatal("cannot decode server_host_key_blob"); | ||
83 | if (server_host_key->type != kex->hostkey_type) | ||
84 | fatal("type mismatch for decoded server_host_key_blob"); | ||
85 | if (kex->verify_host_key == NULL) | ||
86 | fatal("cannot verify server_host_key"); | ||
87 | if (kex->verify_host_key(server_host_key) == -1) | ||
88 | fatal("server_host_key verification failed"); | ||
89 | |||
90 | /* Q_S, server public key */ | ||
91 | if ((server_public = EC_POINT_new(group)) == NULL) | ||
92 | fatal("%s: EC_POINT_new failed", __func__); | ||
93 | packet_get_ecpoint(group, server_public); | ||
94 | |||
95 | if (key_ec_validate_public(group, server_public) != 0) | ||
96 | fatal("%s: invalid server public key", __func__); | ||
97 | |||
98 | #ifdef DEBUG_KEXECDH | ||
99 | fputs("server public key:\n", stderr); | ||
100 | key_dump_ec_point(group, server_public); | ||
101 | #endif | ||
102 | |||
103 | /* signed H */ | ||
104 | signature = packet_get_string(&slen); | ||
105 | packet_check_eom(); | ||
106 | |||
107 | klen = (EC_GROUP_get_degree(group) + 7) / 8; | ||
108 | kbuf = xmalloc(klen); | ||
109 | if (ECDH_compute_key(kbuf, klen, server_public, | ||
110 | client_key, NULL) != (int)klen) | ||
111 | fatal("%s: ECDH_compute_key failed", __func__); | ||
112 | |||
113 | #ifdef DEBUG_KEXECDH | ||
114 | dump_digest("shared secret", kbuf, klen); | ||
115 | #endif | ||
116 | if ((shared_secret = BN_new()) == NULL) | ||
117 | fatal("%s: BN_new failed", __func__); | ||
118 | if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) | ||
119 | fatal("%s: BN_bin2bn failed", __func__); | ||
120 | memset(kbuf, 0, klen); | ||
121 | xfree(kbuf); | ||
122 | |||
123 | /* calc and verify H */ | ||
124 | kex_ecdh_hash( | ||
125 | kex->evp_md, | ||
126 | group, | ||
127 | kex->client_version_string, | ||
128 | kex->server_version_string, | ||
129 | buffer_ptr(&kex->my), buffer_len(&kex->my), | ||
130 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), | ||
131 | server_host_key_blob, sbloblen, | ||
132 | EC_KEY_get0_public_key(client_key), | ||
133 | server_public, | ||
134 | shared_secret, | ||
135 | &hash, &hashlen | ||
136 | ); | ||
137 | xfree(server_host_key_blob); | ||
138 | EC_POINT_clear_free(server_public); | ||
139 | EC_KEY_free(client_key); | ||
140 | |||
141 | if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) | ||
142 | fatal("key_verify failed for server_host_key"); | ||
143 | key_free(server_host_key); | ||
144 | xfree(signature); | ||
145 | |||
146 | /* save session id */ | ||
147 | if (kex->session_id == NULL) { | ||
148 | kex->session_id_len = hashlen; | ||
149 | kex->session_id = xmalloc(kex->session_id_len); | ||
150 | memcpy(kex->session_id, hash, kex->session_id_len); | ||
151 | } | ||
152 | |||
153 | kex_derive_keys(kex, hash, hashlen, shared_secret); | ||
154 | BN_clear_free(shared_secret); | ||
155 | kex_finish(kex); | ||
156 | } | ||
diff --git a/kexecdhs.c b/kexecdhs.c new file mode 100644 index 000000000..d73333893 --- /dev/null +++ b/kexecdhs.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* $OpenBSD: kexecdhs.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | ||
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | #include <sys/types.h> | ||
28 | #include <string.h> | ||
29 | #include <signal.h> | ||
30 | |||
31 | #include <openssl/ecdh.h> | ||
32 | |||
33 | #include "xmalloc.h" | ||
34 | #include "buffer.h" | ||
35 | #include "key.h" | ||
36 | #include "cipher.h" | ||
37 | #include "kex.h" | ||
38 | #include "log.h" | ||
39 | #include "packet.h" | ||
40 | #include "dh.h" | ||
41 | #include "ssh2.h" | ||
42 | #ifdef GSSAPI | ||
43 | #include "ssh-gss.h" | ||
44 | #endif | ||
45 | #include "monitor_wrap.h" | ||
46 | |||
47 | void | ||
48 | kexecdh_server(Kex *kex) | ||
49 | { | ||
50 | EC_POINT *client_public; | ||
51 | EC_KEY *server_key; | ||
52 | const EC_GROUP *group; | ||
53 | BIGNUM *shared_secret; | ||
54 | Key *server_host_private, *server_host_public; | ||
55 | u_char *server_host_key_blob = NULL, *signature = NULL; | ||
56 | u_char *kbuf, *hash; | ||
57 | u_int klen, slen, sbloblen, hashlen; | ||
58 | int curve_nid; | ||
59 | |||
60 | curve_nid = kex_ecdh_name_to_nid(kex->name); | ||
61 | if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL) | ||
62 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | ||
63 | if (EC_KEY_generate_key(server_key) != 1) | ||
64 | fatal("%s: EC_KEY_generate_key failed", __func__); | ||
65 | group = EC_KEY_get0_group(server_key); | ||
66 | |||
67 | #ifdef DEBUG_KEXECDH | ||
68 | fputs("server private key:\n", stderr); | ||
69 | key_dump_ec_key(server_key); | ||
70 | #endif | ||
71 | |||
72 | if (kex->load_host_public_key == NULL || | ||
73 | kex->load_host_private_key == NULL) | ||
74 | fatal("Cannot load hostkey"); | ||
75 | server_host_public = kex->load_host_public_key(kex->hostkey_type); | ||
76 | if (server_host_public == NULL) | ||
77 | fatal("Unsupported hostkey type %d", kex->hostkey_type); | ||
78 | server_host_private = kex->load_host_private_key(kex->hostkey_type); | ||
79 | if (server_host_private == NULL) | ||
80 | fatal("Missing private key for hostkey type %d", | ||
81 | kex->hostkey_type); | ||
82 | |||
83 | debug("expecting SSH2_MSG_KEX_ECDH_INIT"); | ||
84 | packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); | ||
85 | if ((client_public = EC_POINT_new(group)) == NULL) | ||
86 | fatal("%s: EC_POINT_new failed", __func__); | ||
87 | packet_get_ecpoint(group, client_public); | ||
88 | packet_check_eom(); | ||
89 | |||
90 | if (key_ec_validate_public(group, client_public) != 0) | ||
91 | fatal("%s: invalid client public key", __func__); | ||
92 | |||
93 | #ifdef DEBUG_KEXECDH | ||
94 | fputs("client public key:\n", stderr); | ||
95 | key_dump_ec_point(group, client_public); | ||
96 | #endif | ||
97 | |||
98 | /* Calculate shared_secret */ | ||
99 | klen = (EC_GROUP_get_degree(group) + 7) / 8; | ||
100 | kbuf = xmalloc(klen); | ||
101 | if (ECDH_compute_key(kbuf, klen, client_public, | ||
102 | server_key, NULL) != (int)klen) | ||
103 | fatal("%s: ECDH_compute_key failed", __func__); | ||
104 | |||
105 | #ifdef DEBUG_KEXDH | ||
106 | dump_digest("shared secret", kbuf, klen); | ||
107 | #endif | ||
108 | if ((shared_secret = BN_new()) == NULL) | ||
109 | fatal("%s: BN_new failed", __func__); | ||
110 | if (BN_bin2bn(kbuf, klen, shared_secret) == NULL) | ||
111 | fatal("%s: BN_bin2bn failed", __func__); | ||
112 | memset(kbuf, 0, klen); | ||
113 | xfree(kbuf); | ||
114 | |||
115 | /* calc H */ | ||
116 | key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); | ||
117 | kex_ecdh_hash( | ||
118 | kex->evp_md, | ||
119 | group, | ||
120 | kex->client_version_string, | ||
121 | kex->server_version_string, | ||
122 | buffer_ptr(&kex->peer), buffer_len(&kex->peer), | ||
123 | buffer_ptr(&kex->my), buffer_len(&kex->my), | ||
124 | server_host_key_blob, sbloblen, | ||
125 | client_public, | ||
126 | EC_KEY_get0_public_key(server_key), | ||
127 | shared_secret, | ||
128 | &hash, &hashlen | ||
129 | ); | ||
130 | EC_POINT_clear_free(client_public); | ||
131 | |||
132 | /* save session id := H */ | ||
133 | if (kex->session_id == NULL) { | ||
134 | kex->session_id_len = hashlen; | ||
135 | kex->session_id = xmalloc(kex->session_id_len); | ||
136 | memcpy(kex->session_id, hash, kex->session_id_len); | ||
137 | } | ||
138 | |||
139 | /* sign H */ | ||
140 | if (PRIVSEP(key_sign(server_host_private, &signature, &slen, | ||
141 | hash, hashlen)) < 0) | ||
142 | fatal("kexdh_server: key_sign failed"); | ||
143 | |||
144 | /* destroy_sensitive_data(); */ | ||
145 | |||
146 | /* send server hostkey, ECDH pubkey 'Q_S' and signed H */ | ||
147 | packet_start(SSH2_MSG_KEX_ECDH_REPLY); | ||
148 | packet_put_string(server_host_key_blob, sbloblen); | ||
149 | packet_put_ecpoint(group, EC_KEY_get0_public_key(server_key)); | ||
150 | packet_put_string(signature, slen); | ||
151 | packet_send(); | ||
152 | |||
153 | xfree(signature); | ||
154 | xfree(server_host_key_blob); | ||
155 | /* have keys, free server key */ | ||
156 | EC_KEY_free(server_key); | ||
157 | |||
158 | kex_derive_keys(kex, hash, hashlen, shared_secret); | ||
159 | BN_clear_free(shared_secret); | ||
160 | kex_finish(kex); | ||
161 | } | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.c,v 1.91 2010/08/31 09:58:37 djm Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.92 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * read_bignum(): | 3 | * read_bignum(): |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -78,6 +78,8 @@ key_new(int type) | |||
78 | DSA *dsa; | 78 | DSA *dsa; |
79 | k = xcalloc(1, sizeof(*k)); | 79 | k = xcalloc(1, sizeof(*k)); |
80 | k->type = type; | 80 | k->type = type; |
81 | k->ecdsa = NULL; | ||
82 | k->ecdsa_nid = -1; | ||
81 | k->dsa = NULL; | 83 | k->dsa = NULL; |
82 | k->rsa = NULL; | 84 | k->rsa = NULL; |
83 | k->cert = NULL; | 85 | k->cert = NULL; |
@@ -109,6 +111,10 @@ key_new(int type) | |||
109 | fatal("key_new: BN_new failed"); | 111 | fatal("key_new: BN_new failed"); |
110 | k->dsa = dsa; | 112 | k->dsa = dsa; |
111 | break; | 113 | break; |
114 | case KEY_ECDSA: | ||
115 | case KEY_ECDSA_CERT: | ||
116 | /* Cannot do anything until we know the group */ | ||
117 | break; | ||
112 | case KEY_UNSPEC: | 118 | case KEY_UNSPEC: |
113 | break; | 119 | break; |
114 | default: | 120 | default: |
@@ -149,6 +155,10 @@ key_add_private(Key *k) | |||
149 | if ((k->dsa->priv_key = BN_new()) == NULL) | 155 | if ((k->dsa->priv_key = BN_new()) == NULL) |
150 | fatal("key_new_private: BN_new failed"); | 156 | fatal("key_new_private: BN_new failed"); |
151 | break; | 157 | break; |
158 | case KEY_ECDSA: | ||
159 | case KEY_ECDSA_CERT: | ||
160 | /* Cannot do anything until we know the group */ | ||
161 | break; | ||
152 | case KEY_UNSPEC: | 162 | case KEY_UNSPEC: |
153 | break; | 163 | break; |
154 | default: | 164 | default: |
@@ -204,6 +214,12 @@ key_free(Key *k) | |||
204 | DSA_free(k->dsa); | 214 | DSA_free(k->dsa); |
205 | k->dsa = NULL; | 215 | k->dsa = NULL; |
206 | break; | 216 | break; |
217 | case KEY_ECDSA: | ||
218 | case KEY_ECDSA_CERT: | ||
219 | if (k->ecdsa != NULL) | ||
220 | EC_KEY_free(k->ecdsa); | ||
221 | k->ecdsa = NULL; | ||
222 | break; | ||
207 | case KEY_UNSPEC: | 223 | case KEY_UNSPEC: |
208 | break; | 224 | break; |
209 | default: | 225 | default: |
@@ -241,6 +257,8 @@ cert_compare(struct KeyCert *a, struct KeyCert *b) | |||
241 | int | 257 | int |
242 | key_equal_public(const Key *a, const Key *b) | 258 | key_equal_public(const Key *a, const Key *b) |
243 | { | 259 | { |
260 | BN_CTX *bnctx; | ||
261 | |||
244 | if (a == NULL || b == NULL || | 262 | if (a == NULL || b == NULL || |
245 | key_type_plain(a->type) != key_type_plain(b->type)) | 263 | key_type_plain(a->type) != key_type_plain(b->type)) |
246 | return 0; | 264 | return 0; |
@@ -261,6 +279,24 @@ key_equal_public(const Key *a, const Key *b) | |||
261 | BN_cmp(a->dsa->q, b->dsa->q) == 0 && | 279 | BN_cmp(a->dsa->q, b->dsa->q) == 0 && |
262 | BN_cmp(a->dsa->g, b->dsa->g) == 0 && | 280 | BN_cmp(a->dsa->g, b->dsa->g) == 0 && |
263 | BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; | 281 | BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; |
282 | case KEY_ECDSA_CERT: | ||
283 | case KEY_ECDSA: | ||
284 | if (a->ecdsa == NULL || b->ecdsa == NULL || | ||
285 | EC_KEY_get0_public_key(a->ecdsa) == NULL || | ||
286 | EC_KEY_get0_public_key(b->ecdsa) == NULL) | ||
287 | return 0; | ||
288 | if ((bnctx = BN_CTX_new()) == NULL) | ||
289 | fatal("%s: BN_CTX_new failed", __func__); | ||
290 | if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa), | ||
291 | EC_KEY_get0_group(b->ecdsa), bnctx) != 0 || | ||
292 | EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa), | ||
293 | EC_KEY_get0_public_key(a->ecdsa), | ||
294 | EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) { | ||
295 | BN_CTX_free(bnctx); | ||
296 | return 0; | ||
297 | } | ||
298 | BN_CTX_free(bnctx); | ||
299 | return 1; | ||
264 | default: | 300 | default: |
265 | fatal("key_equal: bad key type %d", a->type); | 301 | fatal("key_equal: bad key type %d", a->type); |
266 | } | 302 | } |
@@ -312,12 +348,14 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) | |||
312 | BN_bn2bin(k->rsa->e, blob + nlen); | 348 | BN_bn2bin(k->rsa->e, blob + nlen); |
313 | break; | 349 | break; |
314 | case KEY_DSA: | 350 | case KEY_DSA: |
351 | case KEY_ECDSA: | ||
315 | case KEY_RSA: | 352 | case KEY_RSA: |
316 | key_to_blob(k, &blob, &len); | 353 | key_to_blob(k, &blob, &len); |
317 | break; | 354 | break; |
318 | case KEY_DSA_CERT_V00: | 355 | case KEY_DSA_CERT_V00: |
319 | case KEY_RSA_CERT_V00: | 356 | case KEY_RSA_CERT_V00: |
320 | case KEY_DSA_CERT: | 357 | case KEY_DSA_CERT: |
358 | case KEY_ECDSA_CERT: | ||
321 | case KEY_RSA_CERT: | 359 | case KEY_RSA_CERT: |
322 | /* We want a fingerprint of the _key_ not of the cert */ | 360 | /* We want a fingerprint of the _key_ not of the cert */ |
323 | otype = k->type; | 361 | otype = k->type; |
@@ -612,7 +650,7 @@ key_read(Key *ret, char **cpp) | |||
612 | Key *k; | 650 | Key *k; |
613 | int success = -1; | 651 | int success = -1; |
614 | char *cp, *space; | 652 | char *cp, *space; |
615 | int len, n, type; | 653 | int len, n, type, curve_nid = -1; |
616 | u_int bits; | 654 | u_int bits; |
617 | u_char *blob; | 655 | u_char *blob; |
618 | 656 | ||
@@ -644,9 +682,11 @@ key_read(Key *ret, char **cpp) | |||
644 | case KEY_UNSPEC: | 682 | case KEY_UNSPEC: |
645 | case KEY_RSA: | 683 | case KEY_RSA: |
646 | case KEY_DSA: | 684 | case KEY_DSA: |
685 | case KEY_ECDSA: | ||
647 | case KEY_DSA_CERT_V00: | 686 | case KEY_DSA_CERT_V00: |
648 | case KEY_RSA_CERT_V00: | 687 | case KEY_RSA_CERT_V00: |
649 | case KEY_DSA_CERT: | 688 | case KEY_DSA_CERT: |
689 | case KEY_ECDSA_CERT: | ||
650 | case KEY_RSA_CERT: | 690 | case KEY_RSA_CERT: |
651 | space = strchr(cp, ' '); | 691 | space = strchr(cp, ' '); |
652 | if (space == NULL) { | 692 | if (space == NULL) { |
@@ -655,6 +695,11 @@ key_read(Key *ret, char **cpp) | |||
655 | } | 695 | } |
656 | *space = '\0'; | 696 | *space = '\0'; |
657 | type = key_type_from_name(cp); | 697 | type = key_type_from_name(cp); |
698 | if (key_type_plain(type) == KEY_ECDSA && | ||
699 | (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) { | ||
700 | debug("key_read: invalid curve"); | ||
701 | return -1; | ||
702 | } | ||
658 | *space = ' '; | 703 | *space = ' '; |
659 | if (type == KEY_UNSPEC) { | 704 | if (type == KEY_UNSPEC) { |
660 | debug3("key_read: missing keytype"); | 705 | debug3("key_read: missing keytype"); |
@@ -691,6 +736,12 @@ key_read(Key *ret, char **cpp) | |||
691 | key_free(k); | 736 | key_free(k); |
692 | return -1; | 737 | return -1; |
693 | } | 738 | } |
739 | if (key_type_plain(type) == KEY_ECDSA && | ||
740 | curve_nid != k->ecdsa_nid) { | ||
741 | error("key_read: type mismatch: EC curve mismatch"); | ||
742 | key_free(k); | ||
743 | return -1; | ||
744 | } | ||
694 | /*XXXX*/ | 745 | /*XXXX*/ |
695 | if (key_is_cert(ret)) { | 746 | if (key_is_cert(ret)) { |
696 | if (!key_is_cert(k)) { | 747 | if (!key_is_cert(k)) { |
@@ -721,6 +772,17 @@ key_read(Key *ret, char **cpp) | |||
721 | DSA_print_fp(stderr, ret->dsa, 8); | 772 | DSA_print_fp(stderr, ret->dsa, 8); |
722 | #endif | 773 | #endif |
723 | } | 774 | } |
775 | if (key_type_plain(ret->type) == KEY_ECDSA) { | ||
776 | if (ret->ecdsa != NULL) | ||
777 | EC_KEY_free(ret->ecdsa); | ||
778 | ret->ecdsa = k->ecdsa; | ||
779 | ret->ecdsa_nid = k->ecdsa_nid; | ||
780 | k->ecdsa = NULL; | ||
781 | k->ecdsa_nid = -1; | ||
782 | #ifdef DEBUG_PK | ||
783 | key_dump_ec_key(ret->ecdsa); | ||
784 | #endif | ||
785 | } | ||
724 | success = 1; | 786 | success = 1; |
725 | /*XXXX*/ | 787 | /*XXXX*/ |
726 | key_free(k); | 788 | key_free(k); |
@@ -777,6 +839,11 @@ key_write(const Key *key, FILE *f) | |||
777 | if (key->dsa == NULL) | 839 | if (key->dsa == NULL) |
778 | return 0; | 840 | return 0; |
779 | break; | 841 | break; |
842 | case KEY_ECDSA: | ||
843 | case KEY_ECDSA_CERT: | ||
844 | if (key->ecdsa == NULL) | ||
845 | return 0; | ||
846 | break; | ||
780 | case KEY_RSA: | 847 | case KEY_RSA: |
781 | case KEY_RSA_CERT_V00: | 848 | case KEY_RSA_CERT_V00: |
782 | case KEY_RSA_CERT: | 849 | case KEY_RSA_CERT: |
@@ -810,6 +877,8 @@ key_type(const Key *k) | |||
810 | return "RSA"; | 877 | return "RSA"; |
811 | case KEY_DSA: | 878 | case KEY_DSA: |
812 | return "DSA"; | 879 | return "DSA"; |
880 | case KEY_ECDSA: | ||
881 | return "ECDSA"; | ||
813 | case KEY_RSA_CERT_V00: | 882 | case KEY_RSA_CERT_V00: |
814 | return "RSA-CERT-V00"; | 883 | return "RSA-CERT-V00"; |
815 | case KEY_DSA_CERT_V00: | 884 | case KEY_DSA_CERT_V00: |
@@ -818,6 +887,8 @@ key_type(const Key *k) | |||
818 | return "RSA-CERT"; | 887 | return "RSA-CERT"; |
819 | case KEY_DSA_CERT: | 888 | case KEY_DSA_CERT: |
820 | return "DSA-CERT"; | 889 | return "DSA-CERT"; |
890 | case KEY_ECDSA_CERT: | ||
891 | return "ECDSA-CERT"; | ||
821 | } | 892 | } |
822 | return "unknown"; | 893 | return "unknown"; |
823 | } | 894 | } |
@@ -835,10 +906,10 @@ key_cert_type(const Key *k) | |||
835 | } | 906 | } |
836 | } | 907 | } |
837 | 908 | ||
838 | const char * | 909 | static const char * |
839 | key_ssh_name(const Key *k) | 910 | key_ssh_name_from_type_nid(int type, int nid) |
840 | { | 911 | { |
841 | switch (k->type) { | 912 | switch (type) { |
842 | case KEY_RSA: | 913 | case KEY_RSA: |
843 | return "ssh-rsa"; | 914 | return "ssh-rsa"; |
844 | case KEY_DSA: | 915 | case KEY_DSA: |
@@ -851,10 +922,47 @@ key_ssh_name(const Key *k) | |||
851 | return "ssh-rsa-cert-v01@openssh.com"; | 922 | return "ssh-rsa-cert-v01@openssh.com"; |
852 | case KEY_DSA_CERT: | 923 | case KEY_DSA_CERT: |
853 | return "ssh-dss-cert-v01@openssh.com"; | 924 | return "ssh-dss-cert-v01@openssh.com"; |
925 | case KEY_ECDSA: | ||
926 | switch (nid) { | ||
927 | case NID_X9_62_prime256v1: | ||
928 | return "ecdsa-sha2-nistp256"; | ||
929 | case NID_secp384r1: | ||
930 | return "ecdsa-sha2-nistp384"; | ||
931 | case NID_secp521r1: | ||
932 | return "ecdsa-sha2-nistp521"; | ||
933 | default: | ||
934 | break; | ||
935 | } | ||
936 | break; | ||
937 | case KEY_ECDSA_CERT: | ||
938 | switch (nid) { | ||
939 | case NID_X9_62_prime256v1: | ||
940 | return "ecdsa-sha2-nistp256-cert-v01@openssh.com"; | ||
941 | case NID_secp384r1: | ||
942 | return "ecdsa-sha2-nistp384-cert-v01@openssh.com"; | ||
943 | case NID_secp521r1: | ||
944 | return "ecdsa-sha2-nistp521-cert-v01@openssh.com"; | ||
945 | default: | ||
946 | break; | ||
947 | } | ||
948 | break; | ||
854 | } | 949 | } |
855 | return "ssh-unknown"; | 950 | return "ssh-unknown"; |
856 | } | 951 | } |
857 | 952 | ||
953 | const char * | ||
954 | key_ssh_name(const Key *k) | ||
955 | { | ||
956 | return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid); | ||
957 | } | ||
958 | |||
959 | const char * | ||
960 | key_ssh_name_plain(const Key *k) | ||
961 | { | ||
962 | return key_ssh_name_from_type_nid(key_type_plain(k->type), | ||
963 | k->ecdsa_nid); | ||
964 | } | ||
965 | |||
858 | u_int | 966 | u_int |
859 | key_size(const Key *k) | 967 | key_size(const Key *k) |
860 | { | 968 | { |
@@ -868,6 +976,19 @@ key_size(const Key *k) | |||
868 | case KEY_DSA_CERT_V00: | 976 | case KEY_DSA_CERT_V00: |
869 | case KEY_DSA_CERT: | 977 | case KEY_DSA_CERT: |
870 | return BN_num_bits(k->dsa->p); | 978 | return BN_num_bits(k->dsa->p); |
979 | case KEY_ECDSA: | ||
980 | case KEY_ECDSA_CERT: | ||
981 | switch (k->ecdsa_nid) { | ||
982 | case NID_X9_62_prime256v1: | ||
983 | return 256; | ||
984 | case NID_secp384r1: | ||
985 | return 384; | ||
986 | case NID_secp521r1: | ||
987 | return 521; | ||
988 | default: | ||
989 | break; | ||
990 | } | ||
991 | break; | ||
871 | } | 992 | } |
872 | return 0; | 993 | return 0; |
873 | } | 994 | } |
@@ -897,6 +1018,69 @@ dsa_generate_private_key(u_int bits) | |||
897 | return private; | 1018 | return private; |
898 | } | 1019 | } |
899 | 1020 | ||
1021 | int | ||
1022 | key_ecdsa_bits_to_nid(int bits) | ||
1023 | { | ||
1024 | switch (bits) { | ||
1025 | case 256: | ||
1026 | return NID_X9_62_prime256v1; | ||
1027 | case 384: | ||
1028 | return NID_secp384r1; | ||
1029 | case 521: | ||
1030 | return NID_secp521r1; | ||
1031 | default: | ||
1032 | return -1; | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | /* | ||
1037 | * This is horrid, but OpenSSL's PEM_read_PrivateKey seems not to restore | ||
1038 | * the EC_GROUP nid when loading a key... | ||
1039 | */ | ||
1040 | int | ||
1041 | key_ecdsa_group_to_nid(const EC_GROUP *g) | ||
1042 | { | ||
1043 | EC_GROUP *eg; | ||
1044 | int nids[] = { | ||
1045 | NID_X9_62_prime256v1, | ||
1046 | NID_secp384r1, | ||
1047 | NID_secp521r1, | ||
1048 | -1 | ||
1049 | }; | ||
1050 | u_int i; | ||
1051 | BN_CTX *bnctx; | ||
1052 | |||
1053 | if ((bnctx = BN_CTX_new()) == NULL) | ||
1054 | fatal("%s: BN_CTX_new() failed", __func__); | ||
1055 | for (i = 0; nids[i] != -1; i++) { | ||
1056 | if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) | ||
1057 | fatal("%s: EC_GROUP_new_by_curve_name failed", | ||
1058 | __func__); | ||
1059 | if (EC_GROUP_cmp(g, eg, bnctx) == 0) { | ||
1060 | EC_GROUP_free(eg); | ||
1061 | break; | ||
1062 | } | ||
1063 | EC_GROUP_free(eg); | ||
1064 | } | ||
1065 | BN_CTX_free(bnctx); | ||
1066 | debug3("%s: nid = %d", __func__, nids[i]); | ||
1067 | return nids[i]; | ||
1068 | } | ||
1069 | |||
1070 | static EC_KEY* | ||
1071 | ecdsa_generate_private_key(u_int bits, int *nid) | ||
1072 | { | ||
1073 | EC_KEY *private; | ||
1074 | |||
1075 | if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1) | ||
1076 | fatal("%s: invalid key length", __func__); | ||
1077 | if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) | ||
1078 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | ||
1079 | if (EC_KEY_generate_key(private) != 1) | ||
1080 | fatal("%s: EC_KEY_generate_key failed", __func__); | ||
1081 | return private; | ||
1082 | } | ||
1083 | |||
900 | Key * | 1084 | Key * |
901 | key_generate(int type, u_int bits) | 1085 | key_generate(int type, u_int bits) |
902 | { | 1086 | { |
@@ -905,6 +1089,9 @@ key_generate(int type, u_int bits) | |||
905 | case KEY_DSA: | 1089 | case KEY_DSA: |
906 | k->dsa = dsa_generate_private_key(bits); | 1090 | k->dsa = dsa_generate_private_key(bits); |
907 | break; | 1091 | break; |
1092 | case KEY_ECDSA: | ||
1093 | k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid); | ||
1094 | break; | ||
908 | case KEY_RSA: | 1095 | case KEY_RSA: |
909 | case KEY_RSA1: | 1096 | case KEY_RSA1: |
910 | k->rsa = rsa_generate_private_key(bits); | 1097 | k->rsa = rsa_generate_private_key(bits); |
@@ -981,6 +1168,16 @@ key_from_private(const Key *k) | |||
981 | (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) | 1168 | (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) |
982 | fatal("key_from_private: BN_copy failed"); | 1169 | fatal("key_from_private: BN_copy failed"); |
983 | break; | 1170 | break; |
1171 | case KEY_ECDSA: | ||
1172 | case KEY_ECDSA_CERT: | ||
1173 | n = key_new(k->type); | ||
1174 | n->ecdsa_nid = k->ecdsa_nid; | ||
1175 | if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) | ||
1176 | fatal("%s: EC_KEY_new_by_curve_name failed", __func__); | ||
1177 | if (EC_KEY_set_public_key(n->ecdsa, | ||
1178 | EC_KEY_get0_public_key(k->ecdsa)) != 1) | ||
1179 | fatal("%s: EC_KEY_set_public_key failed", __func__); | ||
1180 | break; | ||
984 | case KEY_RSA: | 1181 | case KEY_RSA: |
985 | case KEY_RSA1: | 1182 | case KEY_RSA1: |
986 | case KEY_RSA_CERT_V00: | 1183 | case KEY_RSA_CERT_V00: |
@@ -1012,6 +1209,11 @@ key_type_from_name(char *name) | |||
1012 | return KEY_RSA; | 1209 | return KEY_RSA; |
1013 | } else if (strcmp(name, "ssh-dss") == 0) { | 1210 | } else if (strcmp(name, "ssh-dss") == 0) { |
1014 | return KEY_DSA; | 1211 | return KEY_DSA; |
1212 | } else if (strcmp(name, "ecdsa") == 0 || | ||
1213 | strcmp(name, "ecdsa-sha2-nistp256") == 0 || | ||
1214 | strcmp(name, "ecdsa-sha2-nistp384") == 0 || | ||
1215 | strcmp(name, "ecdsa-sha2-nistp521") == 0) { | ||
1216 | return KEY_ECDSA; | ||
1015 | } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { | 1217 | } else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) { |
1016 | return KEY_RSA_CERT_V00; | 1218 | return KEY_RSA_CERT_V00; |
1017 | } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { | 1219 | } else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) { |
@@ -1020,12 +1222,33 @@ key_type_from_name(char *name) | |||
1020 | return KEY_RSA_CERT; | 1222 | return KEY_RSA_CERT; |
1021 | } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { | 1223 | } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { |
1022 | return KEY_DSA_CERT; | 1224 | return KEY_DSA_CERT; |
1023 | } | 1225 | } else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 || |
1226 | strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 || | ||
1227 | strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) | ||
1228 | return KEY_ECDSA_CERT; | ||
1229 | |||
1024 | debug2("key_type_from_name: unknown key type '%s'", name); | 1230 | debug2("key_type_from_name: unknown key type '%s'", name); |
1025 | return KEY_UNSPEC; | 1231 | return KEY_UNSPEC; |
1026 | } | 1232 | } |
1027 | 1233 | ||
1028 | int | 1234 | int |
1235 | key_ecdsa_nid_from_name(const char *name) | ||
1236 | { | ||
1237 | if (strcmp(name, "ecdsa-sha2-nistp256") == 0 || | ||
1238 | strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0) | ||
1239 | return NID_X9_62_prime256v1; | ||
1240 | if (strcmp(name, "ecdsa-sha2-nistp384") == 0 || | ||
1241 | strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0) | ||
1242 | return NID_secp384r1; | ||
1243 | if (strcmp(name, "ecdsa-sha2-nistp521") == 0 || | ||
1244 | strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) | ||
1245 | return NID_secp521r1; | ||
1246 | |||
1247 | debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name); | ||
1248 | return -1; | ||
1249 | } | ||
1250 | |||
1251 | int | ||
1029 | key_names_valid2(const char *names) | 1252 | key_names_valid2(const char *names) |
1030 | { | 1253 | { |
1031 | char *s, *cp, *p; | 1254 | char *s, *cp, *p; |
@@ -1146,7 +1369,8 @@ cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen) | |||
1146 | goto out; | 1369 | goto out; |
1147 | } | 1370 | } |
1148 | if (key->cert->signature_key->type != KEY_RSA && | 1371 | if (key->cert->signature_key->type != KEY_RSA && |
1149 | key->cert->signature_key->type != KEY_DSA) { | 1372 | key->cert->signature_key->type != KEY_DSA && |
1373 | key->cert->signature_key->type != KEY_ECDSA) { | ||
1150 | error("%s: Invalid signature key type %s (%d)", __func__, | 1374 | error("%s: Invalid signature key type %s (%d)", __func__, |
1151 | key_type(key->cert->signature_key), | 1375 | key_type(key->cert->signature_key), |
1152 | key->cert->signature_key->type); | 1376 | key->cert->signature_key->type); |
@@ -1186,9 +1410,10 @@ Key * | |||
1186 | key_from_blob(const u_char *blob, u_int blen) | 1410 | key_from_blob(const u_char *blob, u_int blen) |
1187 | { | 1411 | { |
1188 | Buffer b; | 1412 | Buffer b; |
1189 | int rlen, type; | 1413 | int rlen, type, nid = -1; |
1190 | char *ktype = NULL; | 1414 | char *ktype = NULL, *curve = NULL; |
1191 | Key *key = NULL; | 1415 | Key *key = NULL; |
1416 | EC_POINT *q = NULL; | ||
1192 | 1417 | ||
1193 | #ifdef DEBUG_PK | 1418 | #ifdef DEBUG_PK |
1194 | dump_base64(stderr, blob, blen); | 1419 | dump_base64(stderr, blob, blen); |
@@ -1201,6 +1426,8 @@ key_from_blob(const u_char *blob, u_int blen) | |||
1201 | } | 1426 | } |
1202 | 1427 | ||
1203 | type = key_type_from_name(ktype); | 1428 | type = key_type_from_name(ktype); |
1429 | if (key_type_plain(type) == KEY_ECDSA) | ||
1430 | nid = key_ecdsa_nid_from_name(ktype); | ||
1204 | 1431 | ||
1205 | switch (type) { | 1432 | switch (type) { |
1206 | case KEY_RSA_CERT: | 1433 | case KEY_RSA_CERT: |
@@ -1238,6 +1465,41 @@ key_from_blob(const u_char *blob, u_int blen) | |||
1238 | DSA_print_fp(stderr, key->dsa, 8); | 1465 | DSA_print_fp(stderr, key->dsa, 8); |
1239 | #endif | 1466 | #endif |
1240 | break; | 1467 | break; |
1468 | case KEY_ECDSA_CERT: | ||
1469 | (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */ | ||
1470 | /* FALLTHROUGH */ | ||
1471 | case KEY_ECDSA: | ||
1472 | key = key_new(type); | ||
1473 | key->ecdsa_nid = nid; | ||
1474 | if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) { | ||
1475 | error("key_from_blob: can't read ecdsa curve"); | ||
1476 | goto badkey; | ||
1477 | } | ||
1478 | if (key->ecdsa_nid != key_curve_name_to_nid(curve)) { | ||
1479 | error("key_from_blob: ecdsa curve doesn't match type"); | ||
1480 | goto badkey; | ||
1481 | } | ||
1482 | if (key->ecdsa != NULL) | ||
1483 | EC_KEY_free(key->ecdsa); | ||
1484 | if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) | ||
1485 | == NULL) | ||
1486 | fatal("key_from_blob: EC_KEY_new_by_curve_name failed"); | ||
1487 | if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) | ||
1488 | fatal("key_from_blob: EC_POINT_new failed"); | ||
1489 | if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa), | ||
1490 | q) == -1) { | ||
1491 | error("key_from_blob: can't read ecdsa key point"); | ||
1492 | goto badkey; | ||
1493 | } | ||
1494 | if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa), | ||
1495 | q) != 0) | ||
1496 | goto badkey; | ||
1497 | if (EC_KEY_set_public_key(key->ecdsa, q) != 1) | ||
1498 | fatal("key_from_blob: EC_KEY_set_public_key failed"); | ||
1499 | #ifdef DEBUG_PK | ||
1500 | key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q); | ||
1501 | #endif | ||
1502 | break; | ||
1241 | case KEY_UNSPEC: | 1503 | case KEY_UNSPEC: |
1242 | key = key_new(type); | 1504 | key = key_new(type); |
1243 | break; | 1505 | break; |
@@ -1255,6 +1517,10 @@ key_from_blob(const u_char *blob, u_int blen) | |||
1255 | out: | 1517 | out: |
1256 | if (ktype != NULL) | 1518 | if (ktype != NULL) |
1257 | xfree(ktype); | 1519 | xfree(ktype); |
1520 | if (curve != NULL) | ||
1521 | xfree(curve); | ||
1522 | if (q != NULL) | ||
1523 | EC_POINT_free(q); | ||
1258 | buffer_free(&b); | 1524 | buffer_free(&b); |
1259 | return key; | 1525 | return key; |
1260 | } | 1526 | } |
@@ -1274,6 +1540,7 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp) | |||
1274 | case KEY_DSA_CERT_V00: | 1540 | case KEY_DSA_CERT_V00: |
1275 | case KEY_RSA_CERT_V00: | 1541 | case KEY_RSA_CERT_V00: |
1276 | case KEY_DSA_CERT: | 1542 | case KEY_DSA_CERT: |
1543 | case KEY_ECDSA_CERT: | ||
1277 | case KEY_RSA_CERT: | 1544 | case KEY_RSA_CERT: |
1278 | /* Use the existing blob */ | 1545 | /* Use the existing blob */ |
1279 | buffer_append(&b, buffer_ptr(&key->cert->certblob), | 1546 | buffer_append(&b, buffer_ptr(&key->cert->certblob), |
@@ -1286,6 +1553,12 @@ key_to_blob(const Key *key, u_char **blobp, u_int *lenp) | |||
1286 | buffer_put_bignum2(&b, key->dsa->g); | 1553 | buffer_put_bignum2(&b, key->dsa->g); |
1287 | buffer_put_bignum2(&b, key->dsa->pub_key); | 1554 | buffer_put_bignum2(&b, key->dsa->pub_key); |
1288 | break; | 1555 | break; |
1556 | case KEY_ECDSA: | ||
1557 | buffer_put_cstring(&b, key_ssh_name(key)); | ||
1558 | buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid)); | ||
1559 | buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa), | ||
1560 | EC_KEY_get0_public_key(key->ecdsa)); | ||
1561 | break; | ||
1289 | case KEY_RSA: | 1562 | case KEY_RSA: |
1290 | buffer_put_cstring(&b, key_ssh_name(key)); | 1563 | buffer_put_cstring(&b, key_ssh_name(key)); |
1291 | buffer_put_bignum2(&b, key->rsa->e); | 1564 | buffer_put_bignum2(&b, key->rsa->e); |
@@ -1319,6 +1592,9 @@ key_sign( | |||
1319 | case KEY_DSA_CERT: | 1592 | case KEY_DSA_CERT: |
1320 | case KEY_DSA: | 1593 | case KEY_DSA: |
1321 | return ssh_dss_sign(key, sigp, lenp, data, datalen); | 1594 | return ssh_dss_sign(key, sigp, lenp, data, datalen); |
1595 | case KEY_ECDSA_CERT: | ||
1596 | case KEY_ECDSA: | ||
1597 | return ssh_ecdsa_sign(key, sigp, lenp, data, datalen); | ||
1322 | case KEY_RSA_CERT_V00: | 1598 | case KEY_RSA_CERT_V00: |
1323 | case KEY_RSA_CERT: | 1599 | case KEY_RSA_CERT: |
1324 | case KEY_RSA: | 1600 | case KEY_RSA: |
@@ -1347,6 +1623,9 @@ key_verify( | |||
1347 | case KEY_DSA_CERT: | 1623 | case KEY_DSA_CERT: |
1348 | case KEY_DSA: | 1624 | case KEY_DSA: |
1349 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); | 1625 | return ssh_dss_verify(key, signature, signaturelen, data, datalen); |
1626 | case KEY_ECDSA_CERT: | ||
1627 | case KEY_ECDSA: | ||
1628 | return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen); | ||
1350 | case KEY_RSA_CERT_V00: | 1629 | case KEY_RSA_CERT_V00: |
1351 | case KEY_RSA_CERT: | 1630 | case KEY_RSA_CERT: |
1352 | case KEY_RSA: | 1631 | case KEY_RSA: |
@@ -1366,7 +1645,9 @@ key_demote(const Key *k) | |||
1366 | pk = xcalloc(1, sizeof(*pk)); | 1645 | pk = xcalloc(1, sizeof(*pk)); |
1367 | pk->type = k->type; | 1646 | pk->type = k->type; |
1368 | pk->flags = k->flags; | 1647 | pk->flags = k->flags; |
1648 | pk->ecdsa_nid = k->ecdsa_nid; | ||
1369 | pk->dsa = NULL; | 1649 | pk->dsa = NULL; |
1650 | pk->ecdsa = NULL; | ||
1370 | pk->rsa = NULL; | 1651 | pk->rsa = NULL; |
1371 | 1652 | ||
1372 | switch (k->type) { | 1653 | switch (k->type) { |
@@ -1399,6 +1680,16 @@ key_demote(const Key *k) | |||
1399 | if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) | 1680 | if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) |
1400 | fatal("key_demote: BN_dup failed"); | 1681 | fatal("key_demote: BN_dup failed"); |
1401 | break; | 1682 | break; |
1683 | case KEY_ECDSA_CERT: | ||
1684 | key_cert_copy(k, pk); | ||
1685 | /* FALLTHROUGH */ | ||
1686 | case KEY_ECDSA: | ||
1687 | if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL) | ||
1688 | fatal("key_demote: EC_KEY_new_by_curve_name failed"); | ||
1689 | if (EC_KEY_set_public_key(pk->ecdsa, | ||
1690 | EC_KEY_get0_public_key(k->ecdsa)) != 1) | ||
1691 | fatal("key_demote: EC_KEY_set_public_key failed"); | ||
1692 | break; | ||
1402 | default: | 1693 | default: |
1403 | fatal("key_free: bad key type %d", k->type); | 1694 | fatal("key_free: bad key type %d", k->type); |
1404 | break; | 1695 | break; |
@@ -1417,6 +1708,7 @@ key_is_cert(const Key *k) | |||
1417 | case KEY_DSA_CERT_V00: | 1708 | case KEY_DSA_CERT_V00: |
1418 | case KEY_RSA_CERT: | 1709 | case KEY_RSA_CERT: |
1419 | case KEY_DSA_CERT: | 1710 | case KEY_DSA_CERT: |
1711 | case KEY_ECDSA_CERT: | ||
1420 | return 1; | 1712 | return 1; |
1421 | default: | 1713 | default: |
1422 | return 0; | 1714 | return 0; |
@@ -1434,6 +1726,8 @@ key_type_plain(int type) | |||
1434 | case KEY_DSA_CERT_V00: | 1726 | case KEY_DSA_CERT_V00: |
1435 | case KEY_DSA_CERT: | 1727 | case KEY_DSA_CERT: |
1436 | return KEY_DSA; | 1728 | return KEY_DSA; |
1729 | case KEY_ECDSA_CERT: | ||
1730 | return KEY_ECDSA; | ||
1437 | default: | 1731 | default: |
1438 | return type; | 1732 | return type; |
1439 | } | 1733 | } |
@@ -1452,6 +1746,10 @@ key_to_certified(Key *k, int legacy) | |||
1452 | k->cert = cert_new(); | 1746 | k->cert = cert_new(); |
1453 | k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT; | 1747 | k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT; |
1454 | return 0; | 1748 | return 0; |
1749 | case KEY_ECDSA: | ||
1750 | k->cert = cert_new(); | ||
1751 | k->type = KEY_ECDSA_CERT; | ||
1752 | return 0; | ||
1455 | default: | 1753 | default: |
1456 | error("%s: key has incorrect type %s", __func__, key_type(k)); | 1754 | error("%s: key has incorrect type %s", __func__, key_type(k)); |
1457 | return -1; | 1755 | return -1; |
@@ -1473,13 +1771,20 @@ key_drop_cert(Key *k) | |||
1473 | cert_free(k->cert); | 1771 | cert_free(k->cert); |
1474 | k->type = KEY_DSA; | 1772 | k->type = KEY_DSA; |
1475 | return 0; | 1773 | return 0; |
1774 | case KEY_ECDSA_CERT: | ||
1775 | cert_free(k->cert); | ||
1776 | k->type = KEY_ECDSA; | ||
1777 | return 0; | ||
1476 | default: | 1778 | default: |
1477 | error("%s: key has incorrect type %s", __func__, key_type(k)); | 1779 | error("%s: key has incorrect type %s", __func__, key_type(k)); |
1478 | return -1; | 1780 | return -1; |
1479 | } | 1781 | } |
1480 | } | 1782 | } |
1481 | 1783 | ||
1482 | /* Sign a KEY_RSA_CERT or KEY_DSA_CERT, (re-)generating the signed certblob */ | 1784 | /* |
1785 | * Sign a KEY_RSA_CERT, KEY_DSA_CERT or KEY_ECDSA_CERT, (re-)generating | ||
1786 | * the signed certblob | ||
1787 | */ | ||
1483 | int | 1788 | int |
1484 | key_certify(Key *k, Key *ca) | 1789 | key_certify(Key *k, Key *ca) |
1485 | { | 1790 | { |
@@ -1498,7 +1803,8 @@ key_certify(Key *k, Key *ca) | |||
1498 | return -1; | 1803 | return -1; |
1499 | } | 1804 | } |
1500 | 1805 | ||
1501 | if (ca->type != KEY_RSA && ca->type != KEY_DSA) { | 1806 | if (ca->type != KEY_RSA && ca->type != KEY_DSA && |
1807 | ca->type != KEY_ECDSA) { | ||
1502 | error("%s: CA key has unsupported type %s", __func__, | 1808 | error("%s: CA key has unsupported type %s", __func__, |
1503 | key_type(ca)); | 1809 | key_type(ca)); |
1504 | return -1; | 1810 | return -1; |
@@ -1510,7 +1816,7 @@ key_certify(Key *k, Key *ca) | |||
1510 | buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); | 1816 | buffer_put_cstring(&k->cert->certblob, key_ssh_name(k)); |
1511 | 1817 | ||
1512 | /* -v01 certs put nonce first */ | 1818 | /* -v01 certs put nonce first */ |
1513 | if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) { | 1819 | if (!key_cert_is_legacy(k)) { |
1514 | arc4random_buf(&nonce, sizeof(nonce)); | 1820 | arc4random_buf(&nonce, sizeof(nonce)); |
1515 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); | 1821 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); |
1516 | } | 1822 | } |
@@ -1523,6 +1829,13 @@ key_certify(Key *k, Key *ca) | |||
1523 | buffer_put_bignum2(&k->cert->certblob, k->dsa->g); | 1829 | buffer_put_bignum2(&k->cert->certblob, k->dsa->g); |
1524 | buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); | 1830 | buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key); |
1525 | break; | 1831 | break; |
1832 | case KEY_ECDSA_CERT: | ||
1833 | buffer_put_cstring(&k->cert->certblob, | ||
1834 | key_curve_nid_to_name(k->ecdsa_nid)); | ||
1835 | buffer_put_ecpoint(&k->cert->certblob, | ||
1836 | EC_KEY_get0_group(k->ecdsa), | ||
1837 | EC_KEY_get0_public_key(k->ecdsa)); | ||
1838 | break; | ||
1526 | case KEY_RSA_CERT_V00: | 1839 | case KEY_RSA_CERT_V00: |
1527 | case KEY_RSA_CERT: | 1840 | case KEY_RSA_CERT: |
1528 | buffer_put_bignum2(&k->cert->certblob, k->rsa->e); | 1841 | buffer_put_bignum2(&k->cert->certblob, k->rsa->e); |
@@ -1536,7 +1849,7 @@ key_certify(Key *k, Key *ca) | |||
1536 | } | 1849 | } |
1537 | 1850 | ||
1538 | /* -v01 certs have a serial number next */ | 1851 | /* -v01 certs have a serial number next */ |
1539 | if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) | 1852 | if (!key_cert_is_legacy(k)) |
1540 | buffer_put_int64(&k->cert->certblob, k->cert->serial); | 1853 | buffer_put_int64(&k->cert->certblob, k->cert->serial); |
1541 | 1854 | ||
1542 | buffer_put_int(&k->cert->certblob, k->cert->type); | 1855 | buffer_put_int(&k->cert->certblob, k->cert->type); |
@@ -1555,14 +1868,14 @@ key_certify(Key *k, Key *ca) | |||
1555 | buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); | 1868 | buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical)); |
1556 | 1869 | ||
1557 | /* -v01 certs have non-critical options here */ | 1870 | /* -v01 certs have non-critical options here */ |
1558 | if (k->type == KEY_DSA_CERT || k->type == KEY_RSA_CERT) { | 1871 | if (!key_cert_is_legacy(k)) { |
1559 | buffer_put_string(&k->cert->certblob, | 1872 | buffer_put_string(&k->cert->certblob, |
1560 | buffer_ptr(&k->cert->extensions), | 1873 | buffer_ptr(&k->cert->extensions), |
1561 | buffer_len(&k->cert->extensions)); | 1874 | buffer_len(&k->cert->extensions)); |
1562 | } | 1875 | } |
1563 | 1876 | ||
1564 | /* -v00 certs put the nonce at the end */ | 1877 | /* -v00 certs put the nonce at the end */ |
1565 | if (k->type == KEY_DSA_CERT_V00 || k->type == KEY_RSA_CERT_V00) | 1878 | if (key_cert_is_legacy(k)) |
1566 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); | 1879 | buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce)); |
1567 | 1880 | ||
1568 | buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ | 1881 | buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */ |
@@ -1647,3 +1960,201 @@ key_cert_is_legacy(Key *k) | |||
1647 | return 0; | 1960 | return 0; |
1648 | } | 1961 | } |
1649 | } | 1962 | } |
1963 | |||
1964 | int | ||
1965 | key_curve_name_to_nid(const char *name) | ||
1966 | { | ||
1967 | if (strcmp(name, "nistp256") == 0) | ||
1968 | return NID_X9_62_prime256v1; | ||
1969 | else if (strcmp(name, "nistp384") == 0) | ||
1970 | return NID_secp384r1; | ||
1971 | else if (strcmp(name, "nistp521") == 0) | ||
1972 | return NID_secp521r1; | ||
1973 | |||
1974 | debug("%s: unsupported EC curve name \"%.100s\"", __func__, name); | ||
1975 | return -1; | ||
1976 | } | ||
1977 | |||
1978 | const char * | ||
1979 | key_curve_nid_to_name(int nid) | ||
1980 | { | ||
1981 | if (nid == NID_X9_62_prime256v1) | ||
1982 | return "nistp256"; | ||
1983 | else if (nid == NID_secp384r1) | ||
1984 | return "nistp384"; | ||
1985 | else if (nid == NID_secp521r1) | ||
1986 | return "nistp521"; | ||
1987 | |||
1988 | error("%s: unsupported EC curve nid %d", __func__, nid); | ||
1989 | return NULL; | ||
1990 | } | ||
1991 | |||
1992 | int | ||
1993 | key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) | ||
1994 | { | ||
1995 | BN_CTX *bnctx; | ||
1996 | EC_POINT *nq = NULL; | ||
1997 | BIGNUM *order, *x, *y, *tmp; | ||
1998 | int ret = -1; | ||
1999 | |||
2000 | if ((bnctx = BN_CTX_new()) == NULL) | ||
2001 | fatal("%s: BN_CTX_new failed", __func__); | ||
2002 | BN_CTX_start(bnctx); | ||
2003 | |||
2004 | /* | ||
2005 | * We shouldn't ever hit this case because bignum_get_ecpoint() | ||
2006 | * refuses to load GF2m points. | ||
2007 | */ | ||
2008 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != | ||
2009 | NID_X9_62_prime_field) { | ||
2010 | error("%s: group is not a prime field", __func__); | ||
2011 | goto out; | ||
2012 | } | ||
2013 | |||
2014 | /* Q != infinity */ | ||
2015 | if (EC_POINT_is_at_infinity(group, public)) { | ||
2016 | error("%s: received degenerate public key (infinity)", | ||
2017 | __func__); | ||
2018 | goto out; | ||
2019 | } | ||
2020 | |||
2021 | if ((x = BN_CTX_get(bnctx)) == NULL || | ||
2022 | (y = BN_CTX_get(bnctx)) == NULL || | ||
2023 | (order = BN_CTX_get(bnctx)) == NULL || | ||
2024 | (tmp = BN_CTX_get(bnctx)) == NULL) | ||
2025 | fatal("%s: BN_CTX_get failed", __func__); | ||
2026 | |||
2027 | /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ | ||
2028 | if (EC_GROUP_get_order(group, order, bnctx) != 1) | ||
2029 | fatal("%s: EC_GROUP_get_order failed", __func__); | ||
2030 | if (EC_POINT_get_affine_coordinates_GFp(group, public, | ||
2031 | x, y, bnctx) != 1) | ||
2032 | fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); | ||
2033 | if (BN_num_bits(x) <= BN_num_bits(order) / 2) { | ||
2034 | error("%s: public key x coordinate too small: " | ||
2035 | "bits(x) = %d, bits(order)/2 = %d", __func__, | ||
2036 | BN_num_bits(x), BN_num_bits(order) / 2); | ||
2037 | goto out; | ||
2038 | } | ||
2039 | if (BN_num_bits(y) <= BN_num_bits(order) / 2) { | ||
2040 | error("%s: public key y coordinate too small: " | ||
2041 | "bits(y) = %d, bits(order)/2 = %d", __func__, | ||
2042 | BN_num_bits(x), BN_num_bits(order) / 2); | ||
2043 | goto out; | ||
2044 | } | ||
2045 | |||
2046 | /* nQ == infinity (n == order of subgroup) */ | ||
2047 | if ((nq = EC_POINT_new(group)) == NULL) | ||
2048 | fatal("%s: BN_CTX_tmp failed", __func__); | ||
2049 | if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) | ||
2050 | fatal("%s: EC_GROUP_mul failed", __func__); | ||
2051 | if (EC_POINT_is_at_infinity(group, nq) != 1) { | ||
2052 | error("%s: received degenerate public key (nQ != infinity)", | ||
2053 | __func__); | ||
2054 | goto out; | ||
2055 | } | ||
2056 | |||
2057 | /* x < order - 1, y < order - 1 */ | ||
2058 | if (!BN_sub(tmp, order, BN_value_one())) | ||
2059 | fatal("%s: BN_sub failed", __func__); | ||
2060 | if (BN_cmp(x, tmp) >= 0) { | ||
2061 | error("%s: public key x coordinate >= group order - 1", | ||
2062 | __func__); | ||
2063 | goto out; | ||
2064 | } | ||
2065 | if (BN_cmp(y, tmp) >= 0) { | ||
2066 | error("%s: public key y coordinate >= group order - 1", | ||
2067 | __func__); | ||
2068 | goto out; | ||
2069 | } | ||
2070 | ret = 0; | ||
2071 | out: | ||
2072 | BN_CTX_free(bnctx); | ||
2073 | EC_POINT_free(nq); | ||
2074 | return ret; | ||
2075 | } | ||
2076 | |||
2077 | int | ||
2078 | key_ec_validate_private(const EC_KEY *key) | ||
2079 | { | ||
2080 | BN_CTX *bnctx; | ||
2081 | BIGNUM *order, *tmp; | ||
2082 | int ret = -1; | ||
2083 | |||
2084 | if ((bnctx = BN_CTX_new()) == NULL) | ||
2085 | fatal("%s: BN_CTX_new failed", __func__); | ||
2086 | BN_CTX_start(bnctx); | ||
2087 | |||
2088 | if ((order = BN_CTX_get(bnctx)) == NULL || | ||
2089 | (tmp = BN_CTX_get(bnctx)) == NULL) | ||
2090 | fatal("%s: BN_CTX_get failed", __func__); | ||
2091 | |||
2092 | /* log2(private) > log2(order)/2 */ | ||
2093 | if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) | ||
2094 | fatal("%s: EC_GROUP_get_order failed", __func__); | ||
2095 | if (BN_num_bits(EC_KEY_get0_private_key(key)) <= | ||
2096 | BN_num_bits(order) / 2) { | ||
2097 | error("%s: private key too small: " | ||
2098 | "bits(y) = %d, bits(order)/2 = %d", __func__, | ||
2099 | BN_num_bits(EC_KEY_get0_private_key(key)), | ||
2100 | BN_num_bits(order) / 2); | ||
2101 | goto out; | ||
2102 | } | ||
2103 | |||
2104 | /* private < order - 1 */ | ||
2105 | if (!BN_sub(tmp, order, BN_value_one())) | ||
2106 | fatal("%s: BN_sub failed", __func__); | ||
2107 | if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) { | ||
2108 | error("%s: private key >= group order - 1", __func__); | ||
2109 | goto out; | ||
2110 | } | ||
2111 | ret = 0; | ||
2112 | out: | ||
2113 | BN_CTX_free(bnctx); | ||
2114 | return ret; | ||
2115 | } | ||
2116 | |||
2117 | #if defined(DEBUG_KEXECDH) || defined(DEBUG_PK) | ||
2118 | void | ||
2119 | key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) | ||
2120 | { | ||
2121 | BIGNUM *x, *y; | ||
2122 | BN_CTX *bnctx; | ||
2123 | |||
2124 | if (point == NULL) { | ||
2125 | fputs("point=(NULL)\n", stderr); | ||
2126 | return; | ||
2127 | } | ||
2128 | if ((bnctx = BN_CTX_new()) == NULL) | ||
2129 | fatal("%s: BN_CTX_new failed", __func__); | ||
2130 | BN_CTX_start(bnctx); | ||
2131 | if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL) | ||
2132 | fatal("%s: BN_CTX_get failed", __func__); | ||
2133 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) != | ||
2134 | NID_X9_62_prime_field) | ||
2135 | fatal("%s: group is not a prime field", __func__); | ||
2136 | if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1) | ||
2137 | fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); | ||
2138 | fputs("x=", stderr); | ||
2139 | BN_print_fp(stderr, x); | ||
2140 | fputs("\ny=", stderr); | ||
2141 | BN_print_fp(stderr, y); | ||
2142 | fputs("\n", stderr); | ||
2143 | BN_CTX_free(bnctx); | ||
2144 | } | ||
2145 | |||
2146 | void | ||
2147 | key_dump_ec_key(const EC_KEY *key) | ||
2148 | { | ||
2149 | const BIGNUM *exponent; | ||
2150 | |||
2151 | key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key)); | ||
2152 | fputs("exponent=", stderr); | ||
2153 | if ((exponent = EC_KEY_get0_private_key(key)) == NULL) | ||
2154 | fputs("(NULL)", stderr); | ||
2155 | else | ||
2156 | BN_print_fp(stderr, EC_KEY_get0_private_key(key)); | ||
2157 | fputs("\n", stderr); | ||
2158 | } | ||
2159 | #endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */ | ||
2160 | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.h,v 1.30 2010/04/16 01:47:26 djm Exp $ */ | 1 | /* $OpenBSD: key.h,v 1.31 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -29,14 +29,17 @@ | |||
29 | #include "buffer.h" | 29 | #include "buffer.h" |
30 | #include <openssl/rsa.h> | 30 | #include <openssl/rsa.h> |
31 | #include <openssl/dsa.h> | 31 | #include <openssl/dsa.h> |
32 | #include <openssl/ec.h> | ||
32 | 33 | ||
33 | typedef struct Key Key; | 34 | typedef struct Key Key; |
34 | enum types { | 35 | enum types { |
35 | KEY_RSA1, | 36 | KEY_RSA1, |
36 | KEY_RSA, | 37 | KEY_RSA, |
37 | KEY_DSA, | 38 | KEY_DSA, |
39 | KEY_ECDSA, | ||
38 | KEY_RSA_CERT, | 40 | KEY_RSA_CERT, |
39 | KEY_DSA_CERT, | 41 | KEY_DSA_CERT, |
42 | KEY_ECDSA_CERT, | ||
40 | KEY_RSA_CERT_V00, | 43 | KEY_RSA_CERT_V00, |
41 | KEY_DSA_CERT_V00, | 44 | KEY_DSA_CERT_V00, |
42 | KEY_UNSPEC | 45 | KEY_UNSPEC |
@@ -73,6 +76,8 @@ struct Key { | |||
73 | int flags; | 76 | int flags; |
74 | RSA *rsa; | 77 | RSA *rsa; |
75 | DSA *dsa; | 78 | DSA *dsa; |
79 | int ecdsa_nid; /* NID of curve */ | ||
80 | EC_KEY *ecdsa; | ||
76 | struct KeyCert *cert; | 81 | struct KeyCert *cert; |
77 | }; | 82 | }; |
78 | 83 | ||
@@ -104,9 +109,18 @@ int key_cert_check_authority(const Key *, int, int, const char *, | |||
104 | const char **); | 109 | const char **); |
105 | int key_cert_is_legacy(Key *); | 110 | int key_cert_is_legacy(Key *); |
106 | 111 | ||
112 | int key_ecdsa_nid_from_name(const char *); | ||
113 | int key_curve_name_to_nid(const char *); | ||
114 | const char * key_curve_nid_to_name(int); | ||
115 | int key_ecdsa_bits_to_nid(int); | ||
116 | int key_ecdsa_group_to_nid(const EC_GROUP *); | ||
117 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); | ||
118 | int key_ec_validate_private(const EC_KEY *); | ||
119 | |||
107 | Key *key_from_blob(const u_char *, u_int); | 120 | Key *key_from_blob(const u_char *, u_int); |
108 | int key_to_blob(const Key *, u_char **, u_int *); | 121 | int key_to_blob(const Key *, u_char **, u_int *); |
109 | const char *key_ssh_name(const Key *); | 122 | const char *key_ssh_name(const Key *); |
123 | const char *key_ssh_name_plain(const Key *); | ||
110 | int key_names_valid2(const char *); | 124 | int key_names_valid2(const char *); |
111 | 125 | ||
112 | int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 126 | int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); |
@@ -114,7 +128,14 @@ int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | |||
114 | 128 | ||
115 | int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 129 | int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); |
116 | int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 130 | int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); |
131 | int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | ||
132 | int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | ||
117 | int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); | 133 | int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); |
118 | int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); | 134 | int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); |
119 | 135 | ||
136 | #if defined(DEBUG_KEXECDH) || defined(DEBUG_PK) | ||
137 | void key_dump_ec_point(const EC_GROUP *, const EC_POINT *); | ||
138 | void key_dump_ec_key(const EC_KEY *); | ||
139 | #endif | ||
140 | |||
120 | #endif | 141 | #endif |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.108 2010/07/13 23:13:16 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.109 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -1691,6 +1691,7 @@ mm_get_kex(Buffer *m) | |||
1691 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 1691 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
1692 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 1692 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
1693 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 1693 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
1694 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | ||
1694 | kex->server = 1; | 1695 | kex->server = 1; |
1695 | kex->hostkey_type = buffer_get_int(m); | 1696 | kex->hostkey_type = buffer_get_int(m); |
1696 | kex->kex_type = buffer_get_int(m); | 1697 | kex->kex_type = buffer_get_int(m); |
diff --git a/monitor_wrap.c b/monitor_wrap.c index faeb02cfa..1a5dda561 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.c,v 1.69 2010/03/07 11:57:13 dtucker Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.c,v 1.70 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -73,6 +73,7 @@ | |||
73 | #include "misc.h" | 73 | #include "misc.h" |
74 | #include "schnorr.h" | 74 | #include "schnorr.h" |
75 | #include "jpake.h" | 75 | #include "jpake.h" |
76 | #include "uuencode.h" | ||
76 | 77 | ||
77 | #include "channels.h" | 78 | #include "channels.h" |
78 | #include "session.h" | 79 | #include "session.h" |
diff --git a/myproposal.h b/myproposal.h index 7bedfab0a..71f90ee5e 100644 --- a/myproposal.h +++ b/myproposal.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: myproposal.h,v 1.25 2010/04/16 01:47:26 djm Exp $ */ | 1 | /* $OpenBSD: myproposal.h,v 1.26 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -32,20 +32,38 @@ | |||
32 | "diffie-hellman-group-exchange-sha1," \ | 32 | "diffie-hellman-group-exchange-sha1," \ |
33 | "diffie-hellman-group14-sha1," \ | 33 | "diffie-hellman-group14-sha1," \ |
34 | "diffie-hellman-group1-sha1" | 34 | "diffie-hellman-group1-sha1" |
35 | |||
36 | #define KEX_DEFAULT_PK_ALG \ | ||
37 | "ssh-rsa-cert-v01@openssh.com," \ | ||
38 | "ssh-dss-cert-v01@openssh.com," \ | ||
39 | "ssh-rsa-cert-v00@openssh.com," \ | ||
40 | "ssh-dss-cert-v00@openssh.com," \ | ||
41 | "ssh-rsa," \ | ||
42 | "ssh-dss" | ||
35 | #else | 43 | #else |
36 | # define KEX_DEFAULT_KEX \ | 44 | # define KEX_DEFAULT_KEX \ |
45 | "ecdh-sha2-nistp521," \ | ||
46 | "ecdh-sha2-nistp256," \ | ||
47 | "ecdh-sha2-nistp384," \ | ||
37 | "diffie-hellman-group-exchange-sha256," \ | 48 | "diffie-hellman-group-exchange-sha256," \ |
38 | "diffie-hellman-group-exchange-sha1," \ | 49 | "diffie-hellman-group-exchange-sha1," \ |
39 | "diffie-hellman-group14-sha1," \ | 50 | "diffie-hellman-group14-sha1," \ |
40 | "diffie-hellman-group1-sha1" | 51 | "diffie-hellman-group1-sha1" |
41 | #endif | ||
42 | 52 | ||
43 | #define KEX_DEFAULT_PK_ALG \ | 53 | #define KEX_DEFAULT_PK_ALG \ |
44 | "ssh-rsa-cert-v01@openssh.com," \ | 54 | "ecdsa-sha2-nistp256-cert-v01@openssh.com," \ |
45 | "ssh-dss-cert-v01@openssh.com," \ | 55 | "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ |
46 | "ssh-rsa-cert-v00@openssh.com," \ | 56 | "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ |
47 | "ssh-dss-cert-v00@openssh.com," \ | 57 | "ssh-rsa-cert-v01@openssh.com," \ |
48 | "ssh-rsa,ssh-dss" | 58 | "ssh-dss-cert-v01@openssh.com," \ |
59 | "ssh-rsa-cert-v00@openssh.com," \ | ||
60 | "ssh-dss-cert-v00@openssh.com," \ | ||
61 | "ecdsa-sha2-nistp256," \ | ||
62 | "ecdsa-sha2-nistp384," \ | ||
63 | "ecdsa-sha2-nistp521," \ | ||
64 | "ssh-rsa," \ | ||
65 | "ssh-dss" | ||
66 | #endif | ||
49 | 67 | ||
50 | #define KEX_DEFAULT_ENCRYPT \ | 68 | #define KEX_DEFAULT_ENCRYPT \ |
51 | "aes128-ctr,aes192-ctr,aes256-ctr," \ | 69 | "aes128-ctr,aes192-ctr,aes256-ctr," \ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.169 2010/08/31 09:58:37 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.170 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -641,6 +641,12 @@ packet_put_bignum2(BIGNUM * value) | |||
641 | buffer_put_bignum2(&active_state->outgoing_packet, value); | 641 | buffer_put_bignum2(&active_state->outgoing_packet, value); |
642 | } | 642 | } |
643 | 643 | ||
644 | void | ||
645 | packet_put_ecpoint(const EC_GROUP *curve, const EC_POINT *point) | ||
646 | { | ||
647 | buffer_put_ecpoint(&active_state->outgoing_packet, curve, point); | ||
648 | } | ||
649 | |||
644 | /* | 650 | /* |
645 | * Finalizes and sends the packet. If the encryption key has been set, | 651 | * Finalizes and sends the packet. If the encryption key has been set, |
646 | * encrypts the packet before sending. | 652 | * encrypts the packet before sending. |
@@ -1511,6 +1517,12 @@ packet_get_bignum2(BIGNUM * value) | |||
1511 | buffer_get_bignum2(&active_state->incoming_packet, value); | 1517 | buffer_get_bignum2(&active_state->incoming_packet, value); |
1512 | } | 1518 | } |
1513 | 1519 | ||
1520 | void | ||
1521 | packet_get_ecpoint(const EC_GROUP *curve, EC_POINT *point) | ||
1522 | { | ||
1523 | buffer_get_ecpoint(&active_state->incoming_packet, curve, point); | ||
1524 | } | ||
1525 | |||
1514 | void * | 1526 | void * |
1515 | packet_get_raw(u_int *length_ptr) | 1527 | packet_get_raw(u_int *length_ptr) |
1516 | { | 1528 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.h,v 1.53 2010/08/31 09:58:37 djm Exp $ */ | 1 | /* $OpenBSD: packet.h,v 1.54 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -19,6 +19,7 @@ | |||
19 | #include <termios.h> | 19 | #include <termios.h> |
20 | 20 | ||
21 | #include <openssl/bn.h> | 21 | #include <openssl/bn.h> |
22 | #include <openssl/ec.h> | ||
22 | 23 | ||
23 | void packet_set_connection(int, int); | 24 | void packet_set_connection(int, int); |
24 | void packet_set_timeout(int, int); | 25 | void packet_set_timeout(int, int); |
@@ -42,6 +43,7 @@ void packet_put_int(u_int value); | |||
42 | void packet_put_int64(u_int64_t value); | 43 | void packet_put_int64(u_int64_t value); |
43 | void packet_put_bignum(BIGNUM * value); | 44 | void packet_put_bignum(BIGNUM * value); |
44 | void packet_put_bignum2(BIGNUM * value); | 45 | void packet_put_bignum2(BIGNUM * value); |
46 | void packet_put_ecpoint(const EC_GROUP *, const EC_POINT *); | ||
45 | void packet_put_string(const void *buf, u_int len); | 47 | void packet_put_string(const void *buf, u_int len); |
46 | void packet_put_cstring(const char *str); | 48 | void packet_put_cstring(const char *str); |
47 | void packet_put_raw(const void *buf, u_int len); | 49 | void packet_put_raw(const void *buf, u_int len); |
@@ -59,6 +61,7 @@ u_int packet_get_int(void); | |||
59 | u_int64_t packet_get_int64(void); | 61 | u_int64_t packet_get_int64(void); |
60 | void packet_get_bignum(BIGNUM * value); | 62 | void packet_get_bignum(BIGNUM * value); |
61 | void packet_get_bignum2(BIGNUM * value); | 63 | void packet_get_bignum2(BIGNUM * value); |
64 | void packet_get_ecpoint(const EC_GROUP *, EC_POINT *); | ||
62 | void *packet_get_raw(u_int *length_ptr); | 65 | void *packet_get_raw(u_int *length_ptr); |
63 | void *packet_get_string(u_int *length_ptr); | 66 | void *packet_get_string(u_int *length_ptr); |
64 | char *packet_get_cstring(u_int *length_ptr); | 67 | char *packet_get_cstring(u_int *length_ptr); |
diff --git a/pathnames.h b/pathnames.h index 9e50950fe..e2dd49a9b 100644 --- a/pathnames.h +++ b/pathnames.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: pathnames.h,v 1.19 2010/02/11 20:37:47 djm Exp $ */ | 1 | /* $OpenBSD: pathnames.h,v 1.20 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -38,6 +38,7 @@ | |||
38 | #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" | 38 | #define _PATH_HOST_CONFIG_FILE SSHDIR "/ssh_config" |
39 | #define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key" | 39 | #define _PATH_HOST_KEY_FILE SSHDIR "/ssh_host_key" |
40 | #define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" | 40 | #define _PATH_HOST_DSA_KEY_FILE SSHDIR "/ssh_host_dsa_key" |
41 | #define _PATH_HOST_ECDSA_KEY_FILE SSHDIR "/ssh_host_ecdsa_key" | ||
41 | #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" | 42 | #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" |
42 | #define _PATH_DH_MODULI SSHDIR "/moduli" | 43 | #define _PATH_DH_MODULI SSHDIR "/moduli" |
43 | /* Backwards compatibility */ | 44 | /* Backwards compatibility */ |
@@ -74,6 +75,7 @@ | |||
74 | */ | 75 | */ |
75 | #define _PATH_SSH_CLIENT_IDENTITY ".ssh/identity" | 76 | #define _PATH_SSH_CLIENT_IDENTITY ".ssh/identity" |
76 | #define _PATH_SSH_CLIENT_ID_DSA ".ssh/id_dsa" | 77 | #define _PATH_SSH_CLIENT_ID_DSA ".ssh/id_dsa" |
78 | #define _PATH_SSH_CLIENT_ID_ECDSA ".ssh/id_ecdsa" | ||
77 | #define _PATH_SSH_CLIENT_ID_RSA ".ssh/id_rsa" | 79 | #define _PATH_SSH_CLIENT_ID_RSA ".ssh/id_rsa" |
78 | 80 | ||
79 | /* | 81 | /* |
diff --git a/readconf.c b/readconf.c index 0296590e2..98ce3017f 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.187 2010/07/19 09:15:12 djm Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.188 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -1214,6 +1214,12 @@ fill_default_options(Options * options) | |||
1214 | xmalloc(len); | 1214 | xmalloc(len); |
1215 | snprintf(options->identity_files[options->num_identity_files++], | 1215 | snprintf(options->identity_files[options->num_identity_files++], |
1216 | len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); | 1216 | len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA); |
1217 | |||
1218 | len = 2 + strlen(_PATH_SSH_CLIENT_ID_ECDSA) + 1; | ||
1219 | options->identity_files[options->num_identity_files] = | ||
1220 | xmalloc(len); | ||
1221 | snprintf(options->identity_files[options->num_identity_files++], | ||
1222 | len, "~/%.100s", _PATH_SSH_CLIENT_ID_ECDSA); | ||
1217 | } | 1223 | } |
1218 | } | 1224 | } |
1219 | if (options->escape_char == -1) | 1225 | if (options->escape_char == -1) |
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-add.1,v 1.52 2010/03/05 10:28:21 djm Exp $ | 1 | .\" $OpenBSD: ssh-add.1,v 1.53 2010/08/31 11:54:45 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" -*- nroff -*- | 3 | .\" -*- nroff -*- |
4 | .\" | 4 | .\" |
@@ -37,12 +37,12 @@ | |||
37 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 37 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
38 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 38 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
39 | .\" | 39 | .\" |
40 | .Dd $Mdocdate: March 5 2010 $ | 40 | .Dd $Mdocdate: August 31 2010 $ |
41 | .Dt SSH-ADD 1 | 41 | .Dt SSH-ADD 1 |
42 | .Os | 42 | .Os |
43 | .Sh NAME | 43 | .Sh NAME |
44 | .Nm ssh-add | 44 | .Nm ssh-add |
45 | .Nd adds RSA or DSA identities to the authentication agent | 45 | .Nd adds private key identities to the authentication agent |
46 | .Sh SYNOPSIS | 46 | .Sh SYNOPSIS |
47 | .Nm ssh-add | 47 | .Nm ssh-add |
48 | .Op Fl cDdLlXx | 48 | .Op Fl cDdLlXx |
@@ -54,11 +54,12 @@ | |||
54 | .Fl e Ar pkcs11 | 54 | .Fl e Ar pkcs11 |
55 | .Sh DESCRIPTION | 55 | .Sh DESCRIPTION |
56 | .Nm | 56 | .Nm |
57 | adds RSA or DSA identities to the authentication agent, | 57 | adds private key identities to the authentication agent, |
58 | .Xr ssh-agent 1 . | 58 | .Xr ssh-agent 1 . |
59 | When run without arguments, it adds the files | 59 | When run without arguments, it adds the files |
60 | .Pa ~/.ssh/id_rsa , | 60 | .Pa ~/.ssh/id_rsa , |
61 | .Pa ~/.ssh/id_dsa | 61 | .Pa ~/.ssh/id_dsa , |
62 | .Pa ~/.ssh/id_ecdsa | ||
62 | and | 63 | and |
63 | .Pa ~/.ssh/identity . | 64 | .Pa ~/.ssh/identity . |
64 | After loading a private key, | 65 | After loading a private key, |
@@ -165,6 +166,8 @@ socket used to communicate with the agent. | |||
165 | Contains the protocol version 1 RSA authentication identity of the user. | 166 | Contains the protocol version 1 RSA authentication identity of the user. |
166 | .It Pa ~/.ssh/id_dsa | 167 | .It Pa ~/.ssh/id_dsa |
167 | Contains the protocol version 2 DSA authentication identity of the user. | 168 | Contains the protocol version 2 DSA authentication identity of the user. |
169 | .It Pa ~/.ssh/id_ecdsa | ||
170 | Contains the protocol version 2 ECDSA authentication identity of the user. | ||
168 | .It Pa ~/.ssh/id_rsa | 171 | .It Pa ~/.ssh/id_rsa |
169 | Contains the protocol version 2 RSA authentication identity of the user. | 172 | Contains the protocol version 2 RSA authentication identity of the user. |
170 | .El | 173 | .El |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.98 2010/08/16 04:06:06 djm Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.99 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -70,6 +70,7 @@ extern char *__progname; | |||
70 | static char *default_files[] = { | 70 | static char *default_files[] = { |
71 | _PATH_SSH_CLIENT_ID_RSA, | 71 | _PATH_SSH_CLIENT_ID_RSA, |
72 | _PATH_SSH_CLIENT_ID_DSA, | 72 | _PATH_SSH_CLIENT_ID_DSA, |
73 | _PATH_SSH_CLIENT_ID_ECDSA, | ||
73 | _PATH_SSH_CLIENT_IDENTITY, | 74 | _PATH_SSH_CLIENT_IDENTITY, |
74 | NULL | 75 | NULL |
75 | }; | 76 | }; |
diff --git a/ssh-agent.1 b/ssh-agent.1 index f65e8e625..88ad490bc 100644 --- a/ssh-agent.1 +++ b/ssh-agent.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-agent.1,v 1.50 2010/01/17 21:49:09 tedu Exp $ | 1 | .\" $OpenBSD: ssh-agent.1,v 1.51 2010/08/31 11:54:45 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | .\" Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -34,7 +34,7 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .Dd $Mdocdate: January 17 2010 $ | 37 | .Dd $Mdocdate: August 31 2010 $ |
38 | .Dt SSH-AGENT 1 | 38 | .Dt SSH-AGENT 1 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -53,7 +53,7 @@ | |||
53 | .Sh DESCRIPTION | 53 | .Sh DESCRIPTION |
54 | .Nm | 54 | .Nm |
55 | is a program to hold private keys used for public key authentication | 55 | is a program to hold private keys used for public key authentication |
56 | (RSA, DSA). | 56 | (RSA, DSA, ECDSA). |
57 | The idea is that | 57 | The idea is that |
58 | .Nm | 58 | .Nm |
59 | is started in the beginning of an X-session or a login session, and | 59 | is started in the beginning of an X-session or a login session, and |
@@ -114,7 +114,8 @@ When executed without arguments, | |||
114 | .Xr ssh-add 1 | 114 | .Xr ssh-add 1 |
115 | adds the files | 115 | adds the files |
116 | .Pa ~/.ssh/id_rsa , | 116 | .Pa ~/.ssh/id_rsa , |
117 | .Pa ~/.ssh/id_dsa | 117 | .Pa ~/.ssh/id_dsa , |
118 | .Pa ~/.ssh/id_ecdsa | ||
118 | and | 119 | and |
119 | .Pa ~/.ssh/identity . | 120 | .Pa ~/.ssh/identity . |
120 | If the identity has a passphrase, | 121 | If the identity has a passphrase, |
@@ -187,6 +188,8 @@ line terminates. | |||
187 | Contains the protocol version 1 RSA authentication identity of the user. | 188 | Contains the protocol version 1 RSA authentication identity of the user. |
188 | .It Pa ~/.ssh/id_dsa | 189 | .It Pa ~/.ssh/id_dsa |
189 | Contains the protocol version 2 DSA authentication identity of the user. | 190 | Contains the protocol version 2 DSA authentication identity of the user. |
191 | .It Pa ~/.ssh/id_ecdsa | ||
192 | Contains the protocol version 2 ECDSA authentication identity of the user. | ||
190 | .It Pa ~/.ssh/id_rsa | 193 | .It Pa ~/.ssh/id_rsa |
191 | Contains the protocol version 2 RSA authentication identity of the user. | 194 | Contains the protocol version 2 RSA authentication identity of the user. |
192 | .It Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt | 195 | .It Pa /tmp/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt |
diff --git a/ssh-agent.c b/ssh-agent.c index e6725ea88..fbfd79c13 100644 --- a/ssh-agent.c +++ b/ssh-agent.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-agent.c,v 1.168 2010/08/16 04:06:06 djm Exp $ */ | 1 | /* $OpenBSD: ssh-agent.c,v 1.169 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -466,8 +466,10 @@ process_add_identity(SocketEntry *e, int version) | |||
466 | Idtab *tab = idtab_lookup(version); | 466 | Idtab *tab = idtab_lookup(version); |
467 | Identity *id; | 467 | Identity *id; |
468 | int type, success = 0, death = 0, confirm = 0; | 468 | int type, success = 0, death = 0, confirm = 0; |
469 | char *type_name, *comment; | 469 | char *type_name, *comment, *curve; |
470 | Key *k = NULL; | 470 | Key *k = NULL; |
471 | BIGNUM *exponent; | ||
472 | EC_POINT *q; | ||
471 | u_char *cert; | 473 | u_char *cert; |
472 | u_int len; | 474 | u_int len; |
473 | 475 | ||
@@ -490,7 +492,6 @@ process_add_identity(SocketEntry *e, int version) | |||
490 | case 2: | 492 | case 2: |
491 | type_name = buffer_get_string(&e->request, NULL); | 493 | type_name = buffer_get_string(&e->request, NULL); |
492 | type = key_type_from_name(type_name); | 494 | type = key_type_from_name(type_name); |
493 | xfree(type_name); | ||
494 | switch (type) { | 495 | switch (type) { |
495 | case KEY_DSA: | 496 | case KEY_DSA: |
496 | k = key_new_private(type); | 497 | k = key_new_private(type); |
@@ -509,6 +510,57 @@ process_add_identity(SocketEntry *e, int version) | |||
509 | key_add_private(k); | 510 | key_add_private(k); |
510 | buffer_get_bignum2(&e->request, k->dsa->priv_key); | 511 | buffer_get_bignum2(&e->request, k->dsa->priv_key); |
511 | break; | 512 | break; |
513 | case KEY_ECDSA: | ||
514 | k = key_new_private(type); | ||
515 | k->ecdsa_nid = key_ecdsa_nid_from_name(type_name); | ||
516 | curve = buffer_get_string(&e->request, NULL); | ||
517 | if (k->ecdsa_nid != key_curve_name_to_nid(curve)) | ||
518 | fatal("%s: curve names mismatch", __func__); | ||
519 | xfree(curve); | ||
520 | k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); | ||
521 | if (k->ecdsa == NULL) | ||
522 | fatal("%s: EC_KEY_new_by_curve_name failed", | ||
523 | __func__); | ||
524 | q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa)); | ||
525 | if (q == NULL) | ||
526 | fatal("%s: BN_new failed", __func__); | ||
527 | if ((exponent = BN_new()) == NULL) | ||
528 | fatal("%s: BN_new failed", __func__); | ||
529 | buffer_get_ecpoint(&e->request, | ||
530 | EC_KEY_get0_group(k->ecdsa), q); | ||
531 | buffer_get_bignum2(&e->request, exponent); | ||
532 | if (EC_KEY_set_public_key(k->ecdsa, q) != 1) | ||
533 | fatal("%s: EC_KEY_set_public_key failed", | ||
534 | __func__); | ||
535 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) | ||
536 | fatal("%s: EC_KEY_set_private_key failed", | ||
537 | __func__); | ||
538 | if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
539 | EC_KEY_get0_public_key(k->ecdsa)) != 0) | ||
540 | fatal("%s: bad ECDSA public key", __func__); | ||
541 | if (key_ec_validate_private(k->ecdsa) != 0) | ||
542 | fatal("%s: bad ECDSA private key", __func__); | ||
543 | BN_clear_free(exponent); | ||
544 | EC_POINT_free(q); | ||
545 | break; | ||
546 | case KEY_ECDSA_CERT: | ||
547 | cert = buffer_get_string(&e->request, &len); | ||
548 | if ((k = key_from_blob(cert, len)) == NULL) | ||
549 | fatal("Certificate parse failed"); | ||
550 | xfree(cert); | ||
551 | key_add_private(k); | ||
552 | if ((exponent = BN_new()) == NULL) | ||
553 | fatal("%s: BN_new failed", __func__); | ||
554 | buffer_get_bignum2(&e->request, exponent); | ||
555 | if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) | ||
556 | fatal("%s: EC_KEY_set_private_key failed", | ||
557 | __func__); | ||
558 | if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), | ||
559 | EC_KEY_get0_public_key(k->ecdsa)) != 0 || | ||
560 | key_ec_validate_private(k->ecdsa) != 0) | ||
561 | fatal("%s: bad ECDSA key", __func__); | ||
562 | BN_clear_free(exponent); | ||
563 | break; | ||
512 | case KEY_RSA: | 564 | case KEY_RSA: |
513 | k = key_new_private(type); | 565 | k = key_new_private(type); |
514 | buffer_get_bignum2(&e->request, k->rsa->n); | 566 | buffer_get_bignum2(&e->request, k->rsa->n); |
@@ -534,9 +586,11 @@ process_add_identity(SocketEntry *e, int version) | |||
534 | buffer_get_bignum2(&e->request, k->rsa->q); | 586 | buffer_get_bignum2(&e->request, k->rsa->q); |
535 | break; | 587 | break; |
536 | default: | 588 | default: |
589 | xfree(type_name); | ||
537 | buffer_clear(&e->request); | 590 | buffer_clear(&e->request); |
538 | goto send; | 591 | goto send; |
539 | } | 592 | } |
593 | xfree(type_name); | ||
540 | break; | 594 | break; |
541 | } | 595 | } |
542 | /* enable blinding */ | 596 | /* enable blinding */ |
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c new file mode 100644 index 000000000..a1c1bdb60 --- /dev/null +++ b/ssh-ecdsa.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* $OpenBSD */ | ||
2 | /* | ||
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | ||
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * 1. Redistributions of source code must retain the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer. | ||
11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer in the | ||
13 | * documentation and/or other materials provided with the distribution. | ||
14 | * | ||
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
25 | */ | ||
26 | |||
27 | #include <sys/types.h> | ||
28 | |||
29 | #include <openssl/bn.h> | ||
30 | #include <openssl/ec.h> | ||
31 | #include <openssl/ecdsa.h> | ||
32 | #include <openssl/evp.h> | ||
33 | |||
34 | #include <string.h> | ||
35 | |||
36 | #include "xmalloc.h" | ||
37 | #include "buffer.h" | ||
38 | #include "compat.h" | ||
39 | #include "log.h" | ||
40 | #include "key.h" | ||
41 | |||
42 | int | ||
43 | ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, | ||
44 | const u_char *data, u_int datalen) | ||
45 | { | ||
46 | ECDSA_SIG *sig; | ||
47 | const EVP_MD *evp_md = EVP_sha256(); | ||
48 | EVP_MD_CTX md; | ||
49 | u_char digest[EVP_MAX_MD_SIZE]; | ||
50 | u_int len, dlen; | ||
51 | Buffer b, bb; | ||
52 | |||
53 | if (key == NULL || key->ecdsa == NULL || | ||
54 | (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) { | ||
55 | error("%s: no ECDSA key", __func__); | ||
56 | return -1; | ||
57 | } | ||
58 | EVP_DigestInit(&md, evp_md); | ||
59 | EVP_DigestUpdate(&md, data, datalen); | ||
60 | EVP_DigestFinal(&md, digest, &dlen); | ||
61 | |||
62 | sig = ECDSA_do_sign(digest, dlen, key->ecdsa); | ||
63 | memset(digest, 'd', sizeof(digest)); | ||
64 | |||
65 | if (sig == NULL) { | ||
66 | error("%s: sign failed", __func__); | ||
67 | return -1; | ||
68 | } | ||
69 | |||
70 | buffer_init(&bb); | ||
71 | buffer_put_bignum2(&bb, sig->r); | ||
72 | buffer_put_bignum2(&bb, sig->s); | ||
73 | ECDSA_SIG_free(sig); | ||
74 | |||
75 | buffer_init(&b); | ||
76 | buffer_put_cstring(&b, key_ssh_name_plain(key)); | ||
77 | buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb)); | ||
78 | buffer_free(&bb); | ||
79 | len = buffer_len(&b); | ||
80 | if (lenp != NULL) | ||
81 | *lenp = len; | ||
82 | if (sigp != NULL) { | ||
83 | *sigp = xmalloc(len); | ||
84 | memcpy(*sigp, buffer_ptr(&b), len); | ||
85 | } | ||
86 | buffer_free(&b); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | int | ||
91 | ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, | ||
92 | const u_char *data, u_int datalen) | ||
93 | { | ||
94 | ECDSA_SIG *sig; | ||
95 | const EVP_MD *evp_md = EVP_sha256(); | ||
96 | EVP_MD_CTX md; | ||
97 | u_char digest[EVP_MAX_MD_SIZE], *sigblob; | ||
98 | u_int len, dlen; | ||
99 | int rlen, ret; | ||
100 | Buffer b, bb; | ||
101 | |||
102 | if (key == NULL || key->ecdsa == NULL || | ||
103 | (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) { | ||
104 | error("%s: no ECDSA key", __func__); | ||
105 | return -1; | ||
106 | } | ||
107 | |||
108 | /* fetch signature */ | ||
109 | char *ktype; | ||
110 | buffer_init(&b); | ||
111 | buffer_append(&b, signature, signaturelen); | ||
112 | ktype = buffer_get_string(&b, NULL); | ||
113 | if (strcmp(key_ssh_name_plain(key), ktype) != 0) { | ||
114 | error("%s: cannot handle type %s", __func__, ktype); | ||
115 | buffer_free(&b); | ||
116 | xfree(ktype); | ||
117 | return -1; | ||
118 | } | ||
119 | xfree(ktype); | ||
120 | sigblob = buffer_get_string(&b, &len); | ||
121 | rlen = buffer_len(&b); | ||
122 | buffer_free(&b); | ||
123 | if (rlen != 0) { | ||
124 | error("%s: remaining bytes in signature %d", __func__, rlen); | ||
125 | xfree(sigblob); | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | /* parse signature */ | ||
130 | if ((sig = ECDSA_SIG_new()) == NULL) | ||
131 | fatal("%s: ECDSA_SIG_new failed", __func__); | ||
132 | if ((sig->r = BN_new()) == NULL || | ||
133 | (sig->s = BN_new()) == NULL) | ||
134 | fatal("%s: BN_new failed", __func__); | ||
135 | |||
136 | buffer_init(&bb); | ||
137 | buffer_append(&bb, sigblob, len); | ||
138 | buffer_get_bignum2(&bb, sig->r); | ||
139 | buffer_get_bignum2(&bb, sig->s); | ||
140 | if (buffer_len(&bb) != 0) | ||
141 | fatal("%s: remaining bytes in inner sigblob", __func__); | ||
142 | |||
143 | /* clean up */ | ||
144 | memset(sigblob, 0, len); | ||
145 | xfree(sigblob); | ||
146 | |||
147 | /* hash the data */ | ||
148 | EVP_DigestInit(&md, evp_md); | ||
149 | EVP_DigestUpdate(&md, data, datalen); | ||
150 | EVP_DigestFinal(&md, digest, &dlen); | ||
151 | |||
152 | ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); | ||
153 | memset(digest, 'd', sizeof(digest)); | ||
154 | |||
155 | ECDSA_SIG_free(sig); | ||
156 | |||
157 | debug("%s: signature %s", __func__, | ||
158 | ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); | ||
159 | return ret; | ||
160 | } | ||
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 9acd8f8c9..4b95a4e1c 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.98 2010/08/04 06:07:11 djm Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.99 2010/08/31 11:54:45 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" -*- nroff -*- | 3 | .\" -*- nroff -*- |
4 | .\" | 4 | .\" |
@@ -37,7 +37,7 @@ | |||
37 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 37 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
38 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 38 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
39 | .\" | 39 | .\" |
40 | .Dd $Mdocdate: August 4 2010 $ | 40 | .Dd $Mdocdate: August 31 2010 $ |
41 | .Dt SSH-KEYGEN 1 | 41 | .Dt SSH-KEYGEN 1 |
42 | .Os | 42 | .Os |
43 | .Sh NAME | 43 | .Sh NAME |
@@ -125,7 +125,7 @@ | |||
125 | generates, manages and converts authentication keys for | 125 | generates, manages and converts authentication keys for |
126 | .Xr ssh 1 . | 126 | .Xr ssh 1 . |
127 | .Nm | 127 | .Nm |
128 | can create RSA keys for use by SSH protocol version 1 and RSA or DSA | 128 | can create RSA keys for use by SSH protocol version 1 and RSA, DSA or ECDSA |
129 | keys for use by SSH protocol version 2. | 129 | keys for use by SSH protocol version 2. |
130 | The type of key to be generated is specified with the | 130 | The type of key to be generated is specified with the |
131 | .Fl t | 131 | .Fl t |
@@ -142,9 +142,10 @@ See the | |||
142 | section for details. | 142 | section for details. |
143 | .Pp | 143 | .Pp |
144 | Normally each user wishing to use SSH | 144 | Normally each user wishing to use SSH |
145 | with RSA or DSA authentication runs this once to create the authentication | 145 | with public key authentication runs this once to create the authentication |
146 | key in | 146 | key in |
147 | .Pa ~/.ssh/identity , | 147 | .Pa ~/.ssh/identity , |
148 | .Pa ~/.ssh/id_ecdsa , | ||
148 | .Pa ~/.ssh/id_dsa | 149 | .Pa ~/.ssh/id_dsa |
149 | or | 150 | or |
150 | .Pa ~/.ssh/id_rsa . | 151 | .Pa ~/.ssh/id_rsa . |
diff --git a/ssh-keygen.c b/ssh-keygen.c index 93f598004..448585185 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.199 2010/08/16 04:06:06 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.200 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -57,6 +57,7 @@ | |||
57 | /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ | 57 | /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ |
58 | #define DEFAULT_BITS 2048 | 58 | #define DEFAULT_BITS 2048 |
59 | #define DEFAULT_BITS_DSA 1024 | 59 | #define DEFAULT_BITS_DSA 1024 |
60 | #define DEFAULT_BITS_ECDSA 521 | ||
60 | u_int32_t bits = 0; | 61 | u_int32_t bits = 0; |
61 | 62 | ||
62 | /* | 63 | /* |
@@ -176,6 +177,10 @@ ask_filename(struct passwd *pw, const char *prompt) | |||
176 | case KEY_DSA: | 177 | case KEY_DSA: |
177 | name = _PATH_SSH_CLIENT_ID_DSA; | 178 | name = _PATH_SSH_CLIENT_ID_DSA; |
178 | break; | 179 | break; |
180 | case KEY_ECDSA_CERT: | ||
181 | case KEY_ECDSA: | ||
182 | name = _PATH_SSH_CLIENT_ID_ECDSA; | ||
183 | break; | ||
179 | case KEY_RSA_CERT: | 184 | case KEY_RSA_CERT: |
180 | case KEY_RSA_CERT_V00: | 185 | case KEY_RSA_CERT_V00: |
181 | case KEY_RSA: | 186 | case KEY_RSA: |
@@ -260,6 +265,10 @@ do_convert_to_pkcs8(Key *k) | |||
260 | if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) | 265 | if (!PEM_write_DSA_PUBKEY(stdout, k->dsa)) |
261 | fatal("PEM_write_DSA_PUBKEY failed"); | 266 | fatal("PEM_write_DSA_PUBKEY failed"); |
262 | break; | 267 | break; |
268 | case KEY_ECDSA: | ||
269 | if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) | ||
270 | fatal("PEM_write_EC_PUBKEY failed"); | ||
271 | break; | ||
263 | default: | 272 | default: |
264 | fatal("%s: unsupported key type %s", __func__, key_type(k)); | 273 | fatal("%s: unsupported key type %s", __func__, key_type(k)); |
265 | } | 274 | } |
@@ -280,6 +289,7 @@ do_convert_to_pem(Key *k) | |||
280 | fatal("PEM_write_DSAPublicKey failed"); | 289 | fatal("PEM_write_DSAPublicKey failed"); |
281 | break; | 290 | break; |
282 | #endif | 291 | #endif |
292 | /* XXX ECDSA? */ | ||
283 | default: | 293 | default: |
284 | fatal("%s: unsupported key type %s", __func__, key_type(k)); | 294 | fatal("%s: unsupported key type %s", __func__, key_type(k)); |
285 | } | 295 | } |
@@ -539,6 +549,13 @@ do_convert_from_pkcs8(Key **k, int *private) | |||
539 | (*k)->type = KEY_DSA; | 549 | (*k)->type = KEY_DSA; |
540 | (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); | 550 | (*k)->dsa = EVP_PKEY_get1_DSA(pubkey); |
541 | break; | 551 | break; |
552 | case EVP_PKEY_EC: | ||
553 | *k = key_new(KEY_UNSPEC); | ||
554 | (*k)->type = KEY_ECDSA; | ||
555 | (*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey); | ||
556 | (*k)->ecdsa_nid = key_ecdsa_group_to_nid( | ||
557 | EC_KEY_get0_group((*k)->ecdsa)); | ||
558 | break; | ||
542 | default: | 559 | default: |
543 | fatal("%s: unsupported pubkey type %d", __func__, | 560 | fatal("%s: unsupported pubkey type %d", __func__, |
544 | EVP_PKEY_type(pubkey->type)); | 561 | EVP_PKEY_type(pubkey->type)); |
@@ -574,6 +591,7 @@ do_convert_from_pem(Key **k, int *private) | |||
574 | fclose(fp); | 591 | fclose(fp); |
575 | return; | 592 | return; |
576 | } | 593 | } |
594 | /* XXX ECDSA */ | ||
577 | #endif | 595 | #endif |
578 | fatal("%s: unrecognised raw private key format", __func__); | 596 | fatal("%s: unrecognised raw private key format", __func__); |
579 | } | 597 | } |
@@ -614,6 +632,10 @@ do_convert_from(struct passwd *pw) | |||
614 | ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, | 632 | ok = PEM_write_DSAPrivateKey(stdout, k->dsa, NULL, |
615 | NULL, 0, NULL, NULL); | 633 | NULL, 0, NULL, NULL); |
616 | break; | 634 | break; |
635 | case KEY_ECDSA: | ||
636 | ok = PEM_write_ECPrivateKey(stdout, k->ecdsa, NULL, | ||
637 | NULL, 0, NULL, NULL); | ||
638 | break; | ||
617 | case KEY_RSA: | 639 | case KEY_RSA: |
618 | ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, | 640 | ok = PEM_write_RSAPrivateKey(stdout, k->rsa, NULL, |
619 | NULL, 0, NULL, NULL); | 641 | NULL, 0, NULL, NULL); |
@@ -1404,7 +1426,8 @@ do_ca_sign(struct passwd *pw, int argc, char **argv) | |||
1404 | tmp = tilde_expand_filename(argv[i], pw->pw_uid); | 1426 | tmp = tilde_expand_filename(argv[i], pw->pw_uid); |
1405 | if ((public = key_load_public(tmp, &comment)) == NULL) | 1427 | if ((public = key_load_public(tmp, &comment)) == NULL) |
1406 | fatal("%s: unable to open \"%s\"", __func__, tmp); | 1428 | fatal("%s: unable to open \"%s\"", __func__, tmp); |
1407 | if (public->type != KEY_RSA && public->type != KEY_DSA) | 1429 | if (public->type != KEY_RSA && public->type != KEY_DSA && |
1430 | public->type != KEY_ECDSA) | ||
1408 | fatal("%s: key \"%s\" type %s cannot be certified", | 1431 | fatal("%s: key \"%s\" type %s cannot be certified", |
1409 | __func__, tmp, key_type(public)); | 1432 | __func__, tmp, key_type(public)); |
1410 | 1433 | ||
@@ -2086,8 +2109,14 @@ main(int argc, char **argv) | |||
2086 | fprintf(stderr, "unknown key type %s\n", key_type_name); | 2109 | fprintf(stderr, "unknown key type %s\n", key_type_name); |
2087 | exit(1); | 2110 | exit(1); |
2088 | } | 2111 | } |
2089 | if (bits == 0) | 2112 | if (bits == 0) { |
2090 | bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS; | 2113 | if (type == KEY_DSA) |
2114 | bits = DEFAULT_BITS_DSA; | ||
2115 | else if (type == KEY_ECDSA) | ||
2116 | bits = DEFAULT_BITS_ECDSA; | ||
2117 | else | ||
2118 | bits = DEFAULT_BITS; | ||
2119 | } | ||
2091 | maxbits = (type == KEY_DSA) ? | 2120 | maxbits = (type == KEY_DSA) ? |
2092 | OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; | 2121 | OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; |
2093 | if (bits > maxbits) { | 2122 | if (bits > maxbits) { |
@@ -2096,6 +2125,9 @@ main(int argc, char **argv) | |||
2096 | } | 2125 | } |
2097 | if (type == KEY_DSA && bits != 1024) | 2126 | if (type == KEY_DSA && bits != 1024) |
2098 | fatal("DSA keys must be 1024 bits"); | 2127 | fatal("DSA keys must be 1024 bits"); |
2128 | else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(bits) == -1) | ||
2129 | fatal("Invalid ECDSA key length - valid lengths are " | ||
2130 | "256, 384 or 521 bits"); | ||
2099 | if (!quiet) | 2131 | if (!quiet) |
2100 | printf("Generating public/private %s key pair.\n", key_type_name); | 2132 | printf("Generating public/private %s key pair.\n", key_type_name); |
2101 | private = key_generate(type, bits); | 2133 | private = key_generate(type, bits); |
diff --git a/ssh-keyscan.1 b/ssh-keyscan.1 index 78255ff79..fe9bb6e07 100644 --- a/ssh-keyscan.1 +++ b/ssh-keyscan.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keyscan.1,v 1.28 2010/01/09 23:04:13 dtucker Exp $ | 1 | .\" $OpenBSD: ssh-keyscan.1,v 1.29 2010/08/31 11:54:45 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. | 3 | .\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. |
4 | .\" | 4 | .\" |
@@ -6,7 +6,7 @@ | |||
6 | .\" permitted provided that due credit is given to the author and the | 6 | .\" permitted provided that due credit is given to the author and the |
7 | .\" OpenBSD project by leaving this copyright notice intact. | 7 | .\" OpenBSD project by leaving this copyright notice intact. |
8 | .\" | 8 | .\" |
9 | .Dd $Mdocdate: January 9 2010 $ | 9 | .Dd $Mdocdate: August 31 2010 $ |
10 | .Dt SSH-KEYSCAN 1 | 10 | .Dt SSH-KEYSCAN 1 |
11 | .Os | 11 | .Os |
12 | .Sh NAME | 12 | .Sh NAME |
@@ -88,9 +88,10 @@ Specifies the type of the key to fetch from the scanned hosts. | |||
88 | The possible values are | 88 | The possible values are |
89 | .Dq rsa1 | 89 | .Dq rsa1 |
90 | for protocol version 1 and | 90 | for protocol version 1 and |
91 | .Dq rsa | 91 | .Dq dsa , |
92 | .Dq ecdsa | ||
92 | or | 93 | or |
93 | .Dq dsa | 94 | .Dq rsa |
94 | for protocol version 2. | 95 | for protocol version 2. |
95 | Multiple values may be specified by separating them with commas. | 96 | Multiple values may be specified by separating them with commas. |
96 | The default is | 97 | The default is |
@@ -122,7 +123,7 @@ attacks which have begun after the ssh_known_hosts file was created. | |||
122 | host-or-namelist bits exponent modulus | 123 | host-or-namelist bits exponent modulus |
123 | .Ed | 124 | .Ed |
124 | .Pp | 125 | .Pp |
125 | .Pa Output format for rsa and dsa keys: | 126 | .Pa Output format for rsa, dsa and ecdsa keys: |
126 | .Bd -literal | 127 | .Bd -literal |
127 | host-or-namelist keytype base64-encoded-key | 128 | host-or-namelist keytype base64-encoded-key |
128 | .Ed | 129 | .Ed |
@@ -130,9 +131,12 @@ host-or-namelist keytype base64-encoded-key | |||
130 | Where | 131 | Where |
131 | .Pa keytype | 132 | .Pa keytype |
132 | is either | 133 | is either |
133 | .Dq ssh-rsa | 134 | .Dq ecdsa-sha2-nistp256 , |
135 | .Dq ecdsa-sha2-nistp384 , | ||
136 | .Dq ecdsa-sha2-nistp521 , | ||
137 | .Dq ssh-dss | ||
134 | or | 138 | or |
135 | .Dq ssh-dss . | 139 | .Dq ssh-rsa . |
136 | .Pp | 140 | .Pp |
137 | .Pa /etc/ssh/ssh_known_hosts | 141 | .Pa /etc/ssh/ssh_known_hosts |
138 | .Sh EXAMPLES | 142 | .Sh EXAMPLES |
@@ -149,7 +153,7 @@ Find all hosts from the file | |||
149 | which have new or different keys from those in the sorted file | 153 | which have new or different keys from those in the sorted file |
150 | .Pa ssh_known_hosts : | 154 | .Pa ssh_known_hosts : |
151 | .Bd -literal | 155 | .Bd -literal |
152 | $ ssh-keyscan -t rsa,dsa -f ssh_hosts | \e | 156 | $ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \e |
153 | sort -u - ssh_known_hosts | diff ssh_known_hosts - | 157 | sort -u - ssh_known_hosts | diff ssh_known_hosts - |
154 | .Ed | 158 | .Ed |
155 | .Sh SEE ALSO | 159 | .Sh SEE ALSO |
diff --git a/ssh-keyscan.c b/ssh-keyscan.c index b6cf427cd..3fb1214e2 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keyscan.c,v 1.82 2010/06/22 04:54:30 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keyscan.c,v 1.83 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. | 3 | * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. |
4 | * | 4 | * |
@@ -52,9 +52,10 @@ int IPv4or6 = AF_UNSPEC; | |||
52 | 52 | ||
53 | int ssh_port = SSH_DEFAULT_PORT; | 53 | int ssh_port = SSH_DEFAULT_PORT; |
54 | 54 | ||
55 | #define KT_RSA1 1 | 55 | #define KT_RSA1 1 |
56 | #define KT_DSA 2 | 56 | #define KT_DSA 2 |
57 | #define KT_RSA 4 | 57 | #define KT_RSA 4 |
58 | #define KT_ECDSA 8 | ||
58 | 59 | ||
59 | int get_keytypes = KT_RSA; /* Get only RSA keys by default */ | 60 | int get_keytypes = KT_RSA; /* Get only RSA keys by default */ |
60 | 61 | ||
@@ -251,6 +252,7 @@ keygrab_ssh2(con *c) | |||
251 | c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 252 | c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
252 | c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; | 253 | c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; |
253 | c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; | 254 | c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; |
255 | c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client; | ||
254 | c->c_kex->verify_host_key = hostjump; | 256 | c->c_kex->verify_host_key = hostjump; |
255 | 257 | ||
256 | if (!(j = setjmp(kexjmp))) { | 258 | if (!(j = setjmp(kexjmp))) { |
@@ -673,6 +675,9 @@ main(int argc, char **argv) | |||
673 | case KEY_DSA: | 675 | case KEY_DSA: |
674 | get_keytypes |= KT_DSA; | 676 | get_keytypes |= KT_DSA; |
675 | break; | 677 | break; |
678 | case KEY_ECDSA: | ||
679 | get_keytypes |= KT_ECDSA; | ||
680 | break; | ||
676 | case KEY_RSA: | 681 | case KEY_RSA: |
677 | get_keytypes |= KT_RSA; | 682 | get_keytypes |= KT_RSA; |
678 | break; | 683 | break; |
diff --git a/ssh-keysign.8 b/ssh-keysign.8 index 2e47f1203..5e09e0271 100644 --- a/ssh-keysign.8 +++ b/ssh-keysign.8 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keysign.8,v 1.11 2010/08/08 19:36:30 jmc Exp $ | 1 | .\" $OpenBSD: ssh-keysign.8,v 1.12 2010/08/31 11:54:45 djm Exp $ |
2 | .\" | 2 | .\" |
3 | .\" Copyright (c) 2002 Markus Friedl. All rights reserved. | 3 | .\" Copyright (c) 2002 Markus Friedl. All rights reserved. |
4 | .\" | 4 | .\" |
@@ -22,7 +22,7 @@ | |||
22 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 22 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
23 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | .\" | 24 | .\" |
25 | .Dd $Mdocdate: August 8 2010 $ | 25 | .Dd $Mdocdate: August 31 2010 $ |
26 | .Dt SSH-KEYSIGN 8 | 26 | .Dt SSH-KEYSIGN 8 |
27 | .Os | 27 | .Os |
28 | .Sh NAME | 28 | .Sh NAME |
@@ -62,6 +62,7 @@ Controls whether | |||
62 | is enabled. | 62 | is enabled. |
63 | .Pp | 63 | .Pp |
64 | .It Pa /etc/ssh/ssh_host_dsa_key | 64 | .It Pa /etc/ssh/ssh_host_dsa_key |
65 | .It Pa /etc/ssh/ssh_host_ecdsa_key | ||
65 | .It Pa /etc/ssh/ssh_host_rsa_key | 66 | .It Pa /etc/ssh/ssh_host_rsa_key |
66 | These files contain the private parts of the host keys used to | 67 | These files contain the private parts of the host keys used to |
67 | generate the digital signature. | 68 | generate the digital signature. |
@@ -72,6 +73,7 @@ Since they are readable only by root, | |||
72 | must be set-uid root if host-based authentication is used. | 73 | must be set-uid root if host-based authentication is used. |
73 | .Pp | 74 | .Pp |
74 | .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub | 75 | .It Pa /etc/ssh/ssh_host_dsa_key-cert.pub |
76 | .It Pa /etc/ssh/ssh_host_ecdsa_key-cert.pub | ||
75 | .It Pa /etc/ssh/ssh_host_rsa_key-cert.pub | 77 | .It Pa /etc/ssh/ssh_host_rsa_key-cert.pub |
76 | If these files exist they are assumed to contain public certificate | 78 | If these files exist they are assumed to contain public certificate |
77 | information corresponding with the private keys above. | 79 | information corresponding with the private keys above. |
@@ -34,8 +34,8 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: ssh.1,v 1.309 2010/08/08 19:36:30 jmc Exp $ | 37 | .\" $OpenBSD: ssh.1,v 1.310 2010/08/31 11:54:45 djm Exp $ |
38 | .Dd $Mdocdate: August 8 2010 $ | 38 | .Dd $Mdocdate: August 31 2010 $ |
39 | .Dt SSH 1 | 39 | .Dt SSH 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -269,13 +269,14 @@ should use to communicate with a PKCS#11 token providing the user's | |||
269 | private RSA key. | 269 | private RSA key. |
270 | .It Fl i Ar identity_file | 270 | .It Fl i Ar identity_file |
271 | Selects a file from which the identity (private key) for | 271 | Selects a file from which the identity (private key) for |
272 | RSA or DSA authentication is read. | 272 | public key authentication is read. |
273 | The default is | 273 | The default is |
274 | .Pa ~/.ssh/identity | 274 | .Pa ~/.ssh/identity |
275 | for protocol version 1, and | 275 | for protocol version 1, and |
276 | .Pa ~/.ssh/id_rsa | 276 | .Pa ~/.ssh/id_dsa , |
277 | .Pa ~/.ssh/id_ecdsa | ||
277 | and | 278 | and |
278 | .Pa ~/.ssh/id_dsa | 279 | .Pa ~/.ssh/id_rsa |
279 | for protocol version 2. | 280 | for protocol version 2. |
280 | Identity files may also be specified on | 281 | Identity files may also be specified on |
281 | a per-host basis in the configuration file. | 282 | a per-host basis in the configuration file. |
@@ -721,9 +722,9 @@ key pair for authentication purposes. | |||
721 | The server knows the public key, and only the user knows the private key. | 722 | The server knows the public key, and only the user knows the private key. |
722 | .Nm | 723 | .Nm |
723 | implements public key authentication protocol automatically, | 724 | implements public key authentication protocol automatically, |
724 | using either the RSA or DSA algorithms. | 725 | using one of the DSA, ECDSA or RSA algorithms. |
725 | Protocol 1 is restricted to using only RSA keys, | 726 | Protocol 1 is restricted to using only RSA keys, |
726 | but protocol 2 may use either. | 727 | but protocol 2 may use any. |
727 | The | 728 | The |
728 | .Sx HISTORY | 729 | .Sx HISTORY |
729 | section of | 730 | section of |
@@ -748,6 +749,8 @@ This stores the private key in | |||
748 | (protocol 1), | 749 | (protocol 1), |
749 | .Pa ~/.ssh/id_dsa | 750 | .Pa ~/.ssh/id_dsa |
750 | (protocol 2 DSA), | 751 | (protocol 2 DSA), |
752 | .Pa ~/.ssh/id_ecdsa | ||
753 | (protocol 2 ECDSA), | ||
751 | or | 754 | or |
752 | .Pa ~/.ssh/id_rsa | 755 | .Pa ~/.ssh/id_rsa |
753 | (protocol 2 RSA) | 756 | (protocol 2 RSA) |
@@ -756,6 +759,8 @@ and stores the public key in | |||
756 | (protocol 1), | 759 | (protocol 1), |
757 | .Pa ~/.ssh/id_dsa.pub | 760 | .Pa ~/.ssh/id_dsa.pub |
758 | (protocol 2 DSA), | 761 | (protocol 2 DSA), |
762 | .Pa ~/.ssh/id_ecdsa.pub | ||
763 | (protocol 2 ECDSA), | ||
759 | or | 764 | or |
760 | .Pa ~/.ssh/id_rsa.pub | 765 | .Pa ~/.ssh/id_rsa.pub |
761 | (protocol 2 RSA) | 766 | (protocol 2 RSA) |
@@ -1277,7 +1282,8 @@ secret, but the recommended permissions are read/write/execute for the user, | |||
1277 | and not accessible by others. | 1282 | and not accessible by others. |
1278 | .Pp | 1283 | .Pp |
1279 | .It Pa ~/.ssh/authorized_keys | 1284 | .It Pa ~/.ssh/authorized_keys |
1280 | Lists the public keys (RSA/DSA) that can be used for logging in as this user. | 1285 | Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as |
1286 | this user. | ||
1281 | The format of this file is described in the | 1287 | The format of this file is described in the |
1282 | .Xr sshd 8 | 1288 | .Xr sshd 8 |
1283 | manual page. | 1289 | manual page. |
@@ -1298,6 +1304,7 @@ above. | |||
1298 | .Pp | 1304 | .Pp |
1299 | .It Pa ~/.ssh/identity | 1305 | .It Pa ~/.ssh/identity |
1300 | .It Pa ~/.ssh/id_dsa | 1306 | .It Pa ~/.ssh/id_dsa |
1307 | .It Pa ~/.ssh/id_ecdsa | ||
1301 | .It Pa ~/.ssh/id_rsa | 1308 | .It Pa ~/.ssh/id_rsa |
1302 | Contains the private key for authentication. | 1309 | Contains the private key for authentication. |
1303 | These files | 1310 | These files |
@@ -1311,6 +1318,7 @@ sensitive part of this file using 3DES. | |||
1311 | .Pp | 1318 | .Pp |
1312 | .It Pa ~/.ssh/identity.pub | 1319 | .It Pa ~/.ssh/identity.pub |
1313 | .It Pa ~/.ssh/id_dsa.pub | 1320 | .It Pa ~/.ssh/id_dsa.pub |
1321 | .It Pa ~/.ssh/id_ecdsa.pub | ||
1314 | .It Pa ~/.ssh/id_rsa.pub | 1322 | .It Pa ~/.ssh/id_rsa.pub |
1315 | Contains the public key for authentication. | 1323 | Contains the public key for authentication. |
1316 | These files are not | 1324 | These files are not |
@@ -1349,6 +1357,7 @@ The file format and configuration options are described in | |||
1349 | .Pp | 1357 | .Pp |
1350 | .It Pa /etc/ssh/ssh_host_key | 1358 | .It Pa /etc/ssh/ssh_host_key |
1351 | .It Pa /etc/ssh/ssh_host_dsa_key | 1359 | .It Pa /etc/ssh/ssh_host_dsa_key |
1360 | .It Pa /etc/ssh/ssh_host_ecdsa_key | ||
1352 | .It Pa /etc/ssh/ssh_host_rsa_key | 1361 | .It Pa /etc/ssh/ssh_host_rsa_key |
1353 | These three files contain the private parts of the host keys | 1362 | These three files contain the private parts of the host keys |
1354 | and are used for host-based authentication. | 1363 | and are used for host-based authentication. |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.348 2010/08/16 04:06:06 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.349 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -780,7 +780,7 @@ main(int ac, char **av) | |||
780 | sensitive_data.external_keysign = 0; | 780 | sensitive_data.external_keysign = 0; |
781 | if (options.rhosts_rsa_authentication || | 781 | if (options.rhosts_rsa_authentication || |
782 | options.hostbased_authentication) { | 782 | options.hostbased_authentication) { |
783 | sensitive_data.nkeys = 5; | 783 | sensitive_data.nkeys = 7; |
784 | sensitive_data.keys = xcalloc(sensitive_data.nkeys, | 784 | sensitive_data.keys = xcalloc(sensitive_data.nkeys, |
785 | sizeof(Key)); | 785 | sizeof(Key)); |
786 | 786 | ||
@@ -789,25 +789,34 @@ main(int ac, char **av) | |||
789 | _PATH_HOST_KEY_FILE, "", NULL, NULL); | 789 | _PATH_HOST_KEY_FILE, "", NULL, NULL); |
790 | sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, | 790 | sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, |
791 | _PATH_HOST_DSA_KEY_FILE, "", NULL); | 791 | _PATH_HOST_DSA_KEY_FILE, "", NULL); |
792 | sensitive_data.keys[2] = key_load_private_cert(KEY_RSA, | 792 | sensitive_data.keys[2] = key_load_private_cert(KEY_ECDSA, |
793 | _PATH_HOST_ECDSA_KEY_FILE, "", NULL); | ||
794 | sensitive_data.keys[3] = key_load_private_cert(KEY_RSA, | ||
793 | _PATH_HOST_RSA_KEY_FILE, "", NULL); | 795 | _PATH_HOST_RSA_KEY_FILE, "", NULL); |
794 | sensitive_data.keys[3] = key_load_private_type(KEY_DSA, | 796 | sensitive_data.keys[4] = key_load_private_type(KEY_DSA, |
795 | _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); | 797 | _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); |
796 | sensitive_data.keys[4] = key_load_private_type(KEY_RSA, | 798 | sensitive_data.keys[5] = key_load_private_type(KEY_ECDSA, |
799 | _PATH_HOST_ECDSA_KEY_FILE, "", NULL, NULL); | ||
800 | sensitive_data.keys[6] = key_load_private_type(KEY_RSA, | ||
797 | _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); | 801 | _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); |
798 | PRIV_END; | 802 | PRIV_END; |
799 | 803 | ||
800 | if (options.hostbased_authentication == 1 && | 804 | if (options.hostbased_authentication == 1 && |
801 | sensitive_data.keys[0] == NULL && | 805 | sensitive_data.keys[0] == NULL && |
802 | sensitive_data.keys[3] == NULL && | 806 | sensitive_data.keys[4] == NULL && |
803 | sensitive_data.keys[4] == NULL) { | 807 | sensitive_data.keys[5] == NULL && |
808 | sensitive_data.keys[6] == NULL) { | ||
804 | sensitive_data.keys[1] = key_load_cert( | 809 | sensitive_data.keys[1] = key_load_cert( |
805 | _PATH_HOST_DSA_KEY_FILE); | 810 | _PATH_HOST_DSA_KEY_FILE); |
806 | sensitive_data.keys[2] = key_load_cert( | 811 | sensitive_data.keys[2] = key_load_cert( |
812 | _PATH_HOST_ECDSA_KEY_FILE); | ||
813 | sensitive_data.keys[3] = key_load_cert( | ||
807 | _PATH_HOST_RSA_KEY_FILE); | 814 | _PATH_HOST_RSA_KEY_FILE); |
808 | sensitive_data.keys[3] = key_load_public( | ||
809 | _PATH_HOST_DSA_KEY_FILE, NULL); | ||
810 | sensitive_data.keys[4] = key_load_public( | 815 | sensitive_data.keys[4] = key_load_public( |
816 | _PATH_HOST_DSA_KEY_FILE, NULL); | ||
817 | sensitive_data.keys[5] = key_load_public( | ||
818 | _PATH_HOST_ECDSA_KEY_FILE, NULL); | ||
819 | sensitive_data.keys[6] = key_load_public( | ||
811 | _PATH_HOST_RSA_KEY_FILE, NULL); | 820 | _PATH_HOST_RSA_KEY_FILE, NULL); |
812 | sensitive_data.external_keysign = 1; | 821 | sensitive_data.external_keysign = 1; |
813 | } | 822 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh2.h,v 1.13 2010/02/26 20:29:54 djm Exp $ */ | 1 | /* $OpenBSD: ssh2.h,v 1.14 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -98,6 +98,10 @@ | |||
98 | #define SSH2_MSG_KEX_DH_GEX_REPLY 33 | 98 | #define SSH2_MSG_KEX_DH_GEX_REPLY 33 |
99 | #define SSH2_MSG_KEX_DH_GEX_REQUEST 34 | 99 | #define SSH2_MSG_KEX_DH_GEX_REQUEST 34 |
100 | 100 | ||
101 | /* ecdh */ | ||
102 | #define SSH2_MSG_KEX_ECDH_INIT 30 | ||
103 | #define SSH2_MSG_KEX_ECDH_REPLY 31 | ||
104 | |||
101 | /* user authentication: generic */ | 105 | /* user authentication: generic */ |
102 | 106 | ||
103 | #define SSH2_MSG_USERAUTH_REQUEST 50 | 107 | #define SSH2_MSG_USERAUTH_REQUEST 50 |
diff --git a/ssh_config.5 b/ssh_config.5 index ddb806ec0..33038ffcf 100644 --- a/ssh_config.5 +++ b/ssh_config.5 | |||
@@ -34,8 +34,8 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: ssh_config.5,v 1.138 2010/08/04 05:37:01 djm Exp $ | 37 | .\" $OpenBSD: ssh_config.5,v 1.139 2010/08/31 11:54:45 djm Exp $ |
38 | .Dd $Mdocdate: August 4 2010 $ | 38 | .Dd $Mdocdate: August 31 2010 $ |
39 | .Dt SSH_CONFIG 5 | 39 | .Dt SSH_CONFIG 5 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -547,7 +547,15 @@ is similar to | |||
547 | Specifies the protocol version 2 host key algorithms | 547 | Specifies the protocol version 2 host key algorithms |
548 | that the client wants to use in order of preference. | 548 | that the client wants to use in order of preference. |
549 | The default for this option is: | 549 | The default for this option is: |
550 | .Dq ssh-rsa,ssh-dss . | 550 | .Bd -literal -offset 3n |
551 | ecdsa-sha2-nistp256-cert-v01@openssh.com, | ||
552 | ecdsa-sha2-nistp384-cert-v01@openssh.com, | ||
553 | ecdsa-sha2-nistp521-cert-v01@openssh.com, | ||
554 | ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com, | ||
555 | ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com, | ||
556 | ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, | ||
557 | ssh-rsa,ssh-dss | ||
558 | .Ed | ||
551 | .It Cm HostKeyAlias | 559 | .It Cm HostKeyAlias |
552 | Specifies an alias that should be used instead of the | 560 | Specifies an alias that should be used instead of the |
553 | real host name when looking up or saving the host key | 561 | real host name when looking up or saving the host key |
@@ -583,14 +591,15 @@ offers many different identities. | |||
583 | The default is | 591 | The default is |
584 | .Dq no . | 592 | .Dq no . |
585 | .It Cm IdentityFile | 593 | .It Cm IdentityFile |
586 | Specifies a file from which the user's RSA or DSA authentication identity | 594 | Specifies a file from which the user's DSA, ECDSA or DSA authentication |
587 | is read. | 595 | identity is read. |
588 | The default is | 596 | The default is |
589 | .Pa ~/.ssh/identity | 597 | .Pa ~/.ssh/identity |
590 | for protocol version 1, and | 598 | for protocol version 1, and |
591 | .Pa ~/.ssh/id_rsa | 599 | .Pa ~/.ssh/id_dsa , |
600 | .Pa ~/.ssh/id_ecdsa | ||
592 | and | 601 | and |
593 | .Pa ~/.ssh/id_dsa | 602 | .Pa ~/.ssh/id_rsa |
594 | for protocol version 2. | 603 | for protocol version 2. |
595 | Additionally, any identities represented by the authentication agent | 604 | Additionally, any identities represented by the authentication agent |
596 | will be used for authentication. | 605 | will be used for authentication. |
diff --git a/sshconnect.c b/sshconnect.c index f55beffe4..4d3a08551 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.c,v 1.224 2010/04/16 21:14:27 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.c,v 1.225 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -1173,7 +1173,7 @@ show_key_from_file(const char *file, const char *host, int keytype) | |||
1173 | static int | 1173 | static int |
1174 | show_other_keys(const char *host, Key *key) | 1174 | show_other_keys(const char *host, Key *key) |
1175 | { | 1175 | { |
1176 | int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, -1}; | 1176 | int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1}; |
1177 | int i, found = 0; | 1177 | int i, found = 0; |
1178 | 1178 | ||
1179 | for (i = 0; type[i] != -1; i++) { | 1179 | for (i = 0; type[i] != -1; i++) { |
diff --git a/sshconnect2.c b/sshconnect2.c index 4c379ae59..a31a663d4 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.183 2010/04/26 22:28:24 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.184 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -145,6 +145,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
145 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 145 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
146 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; | 146 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; |
147 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; | 147 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; |
148 | kex->kex[KEX_ECDH_SHA2] = kexecdh_client; | ||
148 | kex->client_version_string=client_version_string; | 149 | kex->client_version_string=client_version_string; |
149 | kex->server_version_string=server_version_string; | 150 | kex->server_version_string=server_version_string; |
150 | kex->verify_host_key=&verify_host_key_callback; | 151 | kex->verify_host_key=&verify_host_key_callback; |
@@ -34,8 +34,8 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: sshd.8,v 1.258 2010/08/08 19:36:30 jmc Exp $ | 37 | .\" $OpenBSD: sshd.8,v 1.259 2010/08/31 11:54:45 djm Exp $ |
38 | .Dd $Mdocdate: August 8 2010 $ | 38 | .Dd $Mdocdate: August 31 2010 $ |
39 | .Dt SSHD 8 | 39 | .Dt SSHD 8 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -170,9 +170,10 @@ host key files are normally not readable by anyone but root). | |||
170 | The default is | 170 | The default is |
171 | .Pa /etc/ssh/ssh_host_key | 171 | .Pa /etc/ssh/ssh_host_key |
172 | for protocol version 1, and | 172 | for protocol version 1, and |
173 | .Pa /etc/ssh/ssh_host_rsa_key | 173 | .Pa /etc/ssh/ssh_host_dsa_key , |
174 | .Pa /etc/ssh/ssh_host_ecdsa_key | ||
174 | and | 175 | and |
175 | .Pa /etc/ssh/ssh_host_dsa_key | 176 | .Pa /etc/ssh/ssh_host_rsa_key |
176 | for protocol version 2. | 177 | for protocol version 2. |
177 | It is possible to have multiple host key files for | 178 | It is possible to have multiple host key files for |
178 | the different protocol versions and host key algorithms. | 179 | the different protocol versions and host key algorithms. |
@@ -275,7 +276,7 @@ though this can be changed via the | |||
275 | .Cm Protocol | 276 | .Cm Protocol |
276 | option in | 277 | option in |
277 | .Xr sshd_config 5 . | 278 | .Xr sshd_config 5 . |
278 | Protocol 2 supports both RSA and DSA keys; | 279 | Protocol 2 supports DSA, ECDSA and RSA keys; |
279 | protocol 1 only supports RSA keys. | 280 | protocol 1 only supports RSA keys. |
280 | For both protocols, | 281 | For both protocols, |
281 | each host has a host-specific key, | 282 | each host has a host-specific key, |
@@ -483,6 +484,9 @@ protocol version 1; the | |||
483 | comment field is not used for anything (but may be convenient for the | 484 | comment field is not used for anything (but may be convenient for the |
484 | user to identify the key). | 485 | user to identify the key). |
485 | For protocol version 2 the keytype is | 486 | For protocol version 2 the keytype is |
487 | .Dq ecdsa-sha2-nistp256 , | ||
488 | .Dq ecdsa-sha2-nistp384 , | ||
489 | .Dq ecdsa-sha2-nistp521 , | ||
486 | .Dq ssh-dss | 490 | .Dq ssh-dss |
487 | or | 491 | or |
488 | .Dq ssh-rsa . | 492 | .Dq ssh-rsa . |
@@ -494,6 +498,7 @@ keys up to 16 kilobits. | |||
494 | You don't want to type them in; instead, copy the | 498 | You don't want to type them in; instead, copy the |
495 | .Pa identity.pub , | 499 | .Pa identity.pub , |
496 | .Pa id_dsa.pub , | 500 | .Pa id_dsa.pub , |
501 | .Pa id_ecdsa.pub , | ||
497 | or the | 502 | or the |
498 | .Pa id_rsa.pub | 503 | .Pa id_rsa.pub |
499 | file and edit it. | 504 | file and edit it. |
@@ -792,7 +797,8 @@ secret, but the recommended permissions are read/write/execute for the user, | |||
792 | and not accessible by others. | 797 | and not accessible by others. |
793 | .Pp | 798 | .Pp |
794 | .It Pa ~/.ssh/authorized_keys | 799 | .It Pa ~/.ssh/authorized_keys |
795 | Lists the public keys (RSA/DSA) that can be used for logging in as this user. | 800 | Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in |
801 | as this user. | ||
796 | The format of this file is described above. | 802 | The format of this file is described above. |
797 | The content of the file is not highly sensitive, but the recommended | 803 | The content of the file is not highly sensitive, but the recommended |
798 | permissions are read/write for the user, and not accessible by others. | 804 | permissions are read/write for the user, and not accessible by others. |
@@ -871,6 +877,7 @@ rlogin/rsh. | |||
871 | .Pp | 877 | .Pp |
872 | .It Pa /etc/ssh/ssh_host_key | 878 | .It Pa /etc/ssh/ssh_host_key |
873 | .It Pa /etc/ssh/ssh_host_dsa_key | 879 | .It Pa /etc/ssh/ssh_host_dsa_key |
880 | .It Pa /etc/ssh/ssh_host_ecdsa_key | ||
874 | .It Pa /etc/ssh/ssh_host_rsa_key | 881 | .It Pa /etc/ssh/ssh_host_rsa_key |
875 | These three files contain the private parts of the host keys. | 882 | These three files contain the private parts of the host keys. |
876 | These files should only be owned by root, readable only by root, and not | 883 | These files should only be owned by root, readable only by root, and not |
@@ -881,6 +888,7 @@ does not start if these files are group/world-accessible. | |||
881 | .Pp | 888 | .Pp |
882 | .It Pa /etc/ssh/ssh_host_key.pub | 889 | .It Pa /etc/ssh/ssh_host_key.pub |
883 | .It Pa /etc/ssh/ssh_host_dsa_key.pub | 890 | .It Pa /etc/ssh/ssh_host_dsa_key.pub |
891 | .It Pa /etc/ssh/ssh_host_ecdsa_key.pub | ||
884 | .It Pa /etc/ssh/ssh_host_rsa_key.pub | 892 | .It Pa /etc/ssh/ssh_host_rsa_key.pub |
885 | These three files contain the public parts of the host keys. | 893 | These three files contain the public parts of the host keys. |
886 | These files should be world-readable but writable only by | 894 | These files should be world-readable but writable only by |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.377 2010/08/16 04:06:06 djm Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.378 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -733,6 +733,7 @@ list_hostkey_types(void) | |||
733 | switch (key->type) { | 733 | switch (key->type) { |
734 | case KEY_RSA: | 734 | case KEY_RSA: |
735 | case KEY_DSA: | 735 | case KEY_DSA: |
736 | case KEY_ECDSA: | ||
736 | if (buffer_len(&b) > 0) | 737 | if (buffer_len(&b) > 0) |
737 | buffer_append(&b, ",", 1); | 738 | buffer_append(&b, ",", 1); |
738 | p = key_ssh_name(key); | 739 | p = key_ssh_name(key); |
@@ -748,6 +749,7 @@ list_hostkey_types(void) | |||
748 | case KEY_DSA_CERT_V00: | 749 | case KEY_DSA_CERT_V00: |
749 | case KEY_RSA_CERT: | 750 | case KEY_RSA_CERT: |
750 | case KEY_DSA_CERT: | 751 | case KEY_DSA_CERT: |
752 | case KEY_ECDSA_CERT: | ||
751 | if (buffer_len(&b) > 0) | 753 | if (buffer_len(&b) > 0) |
752 | buffer_append(&b, ",", 1); | 754 | buffer_append(&b, ",", 1); |
753 | p = key_ssh_name(key); | 755 | p = key_ssh_name(key); |
@@ -774,6 +776,7 @@ get_hostkey_by_type(int type, int need_private) | |||
774 | case KEY_DSA_CERT_V00: | 776 | case KEY_DSA_CERT_V00: |
775 | case KEY_RSA_CERT: | 777 | case KEY_RSA_CERT: |
776 | case KEY_DSA_CERT: | 778 | case KEY_DSA_CERT: |
779 | case KEY_ECDSA_CERT: | ||
777 | key = sensitive_data.host_certificates[i]; | 780 | key = sensitive_data.host_certificates[i]; |
778 | break; | 781 | break; |
779 | default: | 782 | default: |
@@ -1576,6 +1579,7 @@ main(int ac, char **av) | |||
1576 | break; | 1579 | break; |
1577 | case KEY_RSA: | 1580 | case KEY_RSA: |
1578 | case KEY_DSA: | 1581 | case KEY_DSA: |
1582 | case KEY_ECDSA: | ||
1579 | sensitive_data.have_ssh2_key = 1; | 1583 | sensitive_data.have_ssh2_key = 1; |
1580 | break; | 1584 | break; |
1581 | } | 1585 | } |
@@ -2302,6 +2306,7 @@ do_ssh2_kex(void) | |||
2302 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; | 2306 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; |
2303 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; | 2307 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; |
2304 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; | 2308 | kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; |
2309 | kex->kex[KEX_ECDH_SHA2] = kexecdh_server; | ||
2305 | kex->server = 1; | 2310 | kex->server = 1; |
2306 | kex->client_version_string=client_version_string; | 2311 | kex->client_version_string=client_version_string; |
2307 | kex->server_version_string=server_version_string; | 2312 | kex->server_version_string=server_version_string; |
diff --git a/sshd_config.5 b/sshd_config.5 index 596a728f8..af3d89b80 100644 --- a/sshd_config.5 +++ b/sshd_config.5 | |||
@@ -34,8 +34,8 @@ | |||
34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 34 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 35 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
36 | .\" | 36 | .\" |
37 | .\" $OpenBSD: sshd_config.5,v 1.125 2010/06/30 07:28:34 jmc Exp $ | 37 | .\" $OpenBSD: sshd_config.5,v 1.126 2010/08/31 11:54:45 djm Exp $ |
38 | .Dd $Mdocdate: June 30 2010 $ | 38 | .Dd $Mdocdate: August 31 2010 $ |
39 | .Dt SSHD_CONFIG 5 | 39 | .Dt SSHD_CONFIG 5 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -470,9 +470,10 @@ used by SSH. | |||
470 | The default is | 470 | The default is |
471 | .Pa /etc/ssh/ssh_host_key | 471 | .Pa /etc/ssh/ssh_host_key |
472 | for protocol version 1, and | 472 | for protocol version 1, and |
473 | .Pa /etc/ssh/ssh_host_rsa_key | 473 | .Pa /etc/ssh/ssh_host_dsa_key , |
474 | .Pa /etc/ssh/ssh_host_ecdsa_key | ||
474 | and | 475 | and |
475 | .Pa /etc/ssh/ssh_host_dsa_key | 476 | .Pa /etc/ssh/ssh_host_rsa_key |
476 | for protocol version 2. | 477 | for protocol version 2. |
477 | Note that | 478 | Note that |
478 | .Xr sshd 8 | 479 | .Xr sshd 8 |
@@ -480,7 +481,8 @@ will refuse to use a file if it is group/world-accessible. | |||
480 | It is possible to have multiple host key files. | 481 | It is possible to have multiple host key files. |
481 | .Dq rsa1 | 482 | .Dq rsa1 |
482 | keys are used for version 1 and | 483 | keys are used for version 1 and |
483 | .Dq dsa | 484 | .Dq dsa , |
485 | .Dq ecdsa | ||
484 | or | 486 | or |
485 | .Dq rsa | 487 | .Dq rsa |
486 | are used for version 2 of the SSH protocol. | 488 | are used for version 2 of the SSH protocol. |
diff --git a/uuencode.c b/uuencode.c index b9e57e993..09d80d2fc 100644 --- a/uuencode.c +++ b/uuencode.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: uuencode.c,v 1.25 2009/03/05 11:30:50 djm Exp $ */ | 1 | /* $OpenBSD: uuencode.c,v 1.26 2010/08/31 11:54:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -72,7 +72,7 @@ uudecode(const char *src, u_char *target, size_t targsize) | |||
72 | } | 72 | } |
73 | 73 | ||
74 | void | 74 | void |
75 | dump_base64(FILE *fp, u_char *data, u_int len) | 75 | dump_base64(FILE *fp, const u_char *data, u_int len) |
76 | { | 76 | { |
77 | char *buf; | 77 | char *buf; |
78 | int i, n; | 78 | int i, n; |
diff --git a/uuencode.h b/uuencode.h index fec55b491..4d9888126 100644 --- a/uuencode.h +++ b/uuencode.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: uuencode.h,v 1.13 2006/08/03 03:34:42 deraadt Exp $ */ | 1 | /* $OpenBSD: uuencode.h,v 1.14 2010/08/31 11:54:45 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -26,4 +26,4 @@ | |||
26 | 26 | ||
27 | int uuencode(const u_char *, u_int, char *, size_t); | 27 | int uuencode(const u_char *, u_int, char *, size_t); |
28 | int uudecode(const char *, u_char *, size_t); | 28 | int uudecode(const char *, u_char *, size_t); |
29 | void dump_base64(FILE *, u_char *, u_int); | 29 | void dump_base64(FILE *, const u_char *, u_int); |