summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--PROTOCOL45
-rw-r--r--PROTOCOL.agent44
-rw-r--r--PROTOCOL.certkeys89
-rw-r--r--auth2-jpake.c7
-rw-r--r--authfd.c20
-rw-r--r--authfile.c32
-rw-r--r--bufec.c140
-rw-r--r--buffer.h9
-rw-r--r--dns.c3
-rw-r--r--kex.c10
-rw-r--r--kex.h16
-rw-r--r--kexecdh.c108
-rw-r--r--kexecdhc.c156
-rw-r--r--kexecdhs.c161
-rw-r--r--key.c541
-rw-r--r--key.h23
-rw-r--r--monitor.c3
-rw-r--r--monitor_wrap.c3
-rw-r--r--myproposal.h32
-rw-r--r--packet.c14
-rw-r--r--packet.h5
-rw-r--r--pathnames.h4
-rw-r--r--readconf.c8
-rw-r--r--ssh-add.113
-rw-r--r--ssh-add.c3
-rw-r--r--ssh-agent.111
-rw-r--r--ssh-agent.c60
-rw-r--r--ssh-ecdsa.c160
-rw-r--r--ssh-keygen.19
-rw-r--r--ssh-keygen.c40
-rw-r--r--ssh-keyscan.120
-rw-r--r--ssh-keyscan.c13
-rw-r--r--ssh-keysign.86
-rw-r--r--ssh.125
-rw-r--r--ssh.c27
-rw-r--r--ssh2.h6
-rw-r--r--ssh_config.523
-rw-r--r--sshconnect.c4
-rw-r--r--sshconnect2.c3
-rw-r--r--sshd.820
-rw-r--r--sshd.c7
-rw-r--r--sshd_config.512
-rw-r--r--uuencode.c4
-rw-r--r--uuencode.h4
45 files changed, 1793 insertions, 173 deletions
diff --git a/ChangeLog b/ChangeLog
index 2f4acd9de..889580e5e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
2920100827 5220100827
30 - (dtucker) [contrib/redhat/sshd.init] Bug #1810: initlog is deprecated, 53 - (dtucker) [contrib/redhat/sshd.init] Bug #1810: initlog is deprecated,
diff --git a/PROTOCOL b/PROTOCOL
index 5fc31eade..5d2a7118a 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -12,7 +12,9 @@ are individually implemented as extensions described below.
12The protocol used by OpenSSH's ssh-agent is described in the file 12The protocol used by OpenSSH's ssh-agent is described in the file
13PROTOCOL.agent 13PROTOCOL.agent
14 14
151. transport: Protocol 2 MAC algorithm "umac-64@openssh.com" 151. Transport protocol changes
16
171.1. transport: Protocol 2 MAC algorithm "umac-64@openssh.com"
16 18
17This is a new transport-layer MAC method using the UMAC algorithm 19This 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
21http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt 23http://www.openssh.com/txt/draft-miller-secsh-umac-01.txt
22 24
232. transport: Protocol 2 compression algorithm "zlib@openssh.com" 251.2. transport: Protocol 2 compression algorithm "zlib@openssh.com"
24 26
25This transport-layer compression method uses the zlib compression 27This transport-layer compression method uses the zlib compression
26algorithm (identical to the "zlib" method in rfc4253), but delays the 28algorithm (identical to the "zlib" method in rfc4253), but delays the
@@ -31,14 +33,27 @@ The method is documented in:
31 33
32http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt 34http://www.openssh.com/txt/draft-miller-secsh-compression-delayed-00.txt
33 35
343. transport: New public key algorithms "ssh-rsa-cert-v00@openssh.com" and 361.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
37OpenSSH introduces two new public key algorithms to support certificate 42OpenSSH introduces new public key algorithms to support certificate
38authentication for users and hostkeys. These methods are documented in 43authentication for users and hostkeys. These methods are documented in
39the file PROTOCOL.certkeys 44the file PROTOCOL.certkeys
40 45
414. connection: Channel write close extension "eow@openssh.com" 461.4. transport: Elliptic Curve cryptography
47
48OpenSSH supports ECC key exchange and public key authentication as
49specified in RFC5656. Only the ecdsa-sha2-nistp256, ecdsa-sha2-nistp384
50and ecdsa-sha2-nistp521 curves over GF(p) are supported. Elliptic
51curve points encoded using point compression are NOT accepted or
52generated.
53
542. Connection protocol changes
55
562.1. connection: Channel write close extension "eow@openssh.com"
42 57
43The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF 58The SSH connection protocol (rfc4254) provides the SSH_MSG_CHANNEL_EOF
44message to allow an endpoint to signal its peer that it will send no 59message 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).
77Other SSH implementations may be whitelisted to receive this message 92Other SSH implementations may be whitelisted to receive this message
78upon request. 93upon request.
79 94
805. connection: disallow additional sessions extension 952.2. connection: disallow additional sessions extension
81 "no-more-sessions@openssh.com" 96 "no-more-sessions@openssh.com"
82 97
83Most SSH connections will only ever request a single session, but a 98Most SSH connections will only ever request a single session, but a
84attacker may abuse a running ssh client to surreptitiously open 99attacker 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
105servers (identified by banner). Other SSH implementations may be 120servers (identified by banner). Other SSH implementations may be
106whitelisted to receive this message upon request. 121whitelisted to receive this message upon request.
107 122
1086. connection: Tunnel forward extension "tun@openssh.com" 1232.3. connection: Tunnel forward extension "tun@openssh.com"
109 124
110OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com" 125OpenSSH supports layer 2 and layer 3 tunnelling via the "tun@openssh.com"
111channel type. This channel type supports forwarding of network packets 126channel type. This channel type supports forwarding of network packets
@@ -166,7 +181,9 @@ The contents of the "data" field for layer 2 packets is:
166The "frame" field contains an IEEE 802.3 Ethernet frame, including 181The "frame" field contains an IEEE 802.3 Ethernet frame, including
167header. 182header.
168 183
1697. sftp: Reversal of arguments to SSH_FXP_SYMLINK 1843. SFTP protocol changes
185
1863.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
170 187
171When OpenSSH's sftp-server was implemented, the order of the arguments 188When OpenSSH's sftp-server was implemented, the order of the arguments
172to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately, 189to 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
1828. sftp: Server extension announcement in SSH_FXP_VERSION 1993.2. sftp: Server extension announcement in SSH_FXP_VERSION
183 200
184OpenSSH's sftp-server lists the extensions it supports using the 201OpenSSH's sftp-server lists the extensions it supports using the
185standard extension announcement mechanism in the SSH_FXP_VERSION server 202standard 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
200extension with multiple versions (though this is unlikely). Clients MUST 217extension with multiple versions (though this is unlikely). Clients MUST
201check the version number before attempting to use the extension. 218check the version number before attempting to use the extension.
202 219
2039. sftp: Extension request "posix-rename@openssh.com" 2203.3. sftp: Extension request "posix-rename@openssh.com"
204 221
205This operation provides a rename operation with POSIX semantics, which 222This operation provides a rename operation with POSIX semantics, which
206are different to those provided by the standard SSH_FXP_RENAME in 223are 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.
217This extension is advertised in the SSH_FXP_VERSION hello with version 234This extension is advertised in the SSH_FXP_VERSION hello with version
218"1". 235"1".
219 236
22010. sftp: Extension requests "statvfs@openssh.com" and 2373.4. sftp: Extension requests "statvfs@openssh.com" and
221 "fstatvfs@openssh.com" 238 "fstatvfs@openssh.com"
222 239
223These requests correspond to the statvfs and fstatvfs POSIX system 240These requests correspond to the statvfs and fstatvfs POSIX system
@@ -258,4 +275,4 @@ The values of the f_flag bitmask are as follows:
258Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are 275Both the "statvfs@openssh.com" and "fstatvfs@openssh.com" extensions are
259advertised in the SSH_FXP_VERSION hello with version "2". 276advertised 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
1602.2.3 Add protocol 2 key 1602.2.3 Add protocol 2 key
161 161
162The OpenSSH agent supports DSA and RSA keys for protocol 2. DSA keys may 162The OpenSSH agent supports DSA, ECDSA and RSA keys for protocol 2. DSA
163be added using the following request 163keys 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
185ECDSA 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
198ECDSA 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
185RSA keys may be added with this request: 209RSA 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
214protocol 1 "add key" request, the private key is overspecified to avoid 238protocol 1 "add key" request, the private key is overspecified to avoid
215redundant processing. 239redundant processing.
216 240
217For both DSA and RSA key add requests, "key_constraints" may only be 241For DSA, ECDSA and RSA key add requests, "key_constraints" may only be
218present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED. 242present if the request type is SSH2_AGENTC_ADD_ID_CONSTRAINED.
219 243
220The agent will reply with a SSH_AGENT_SUCCESS if the key has been 244The 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
296Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key 320Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
297Algorithms" for either of the supported key types: "ssh-dss" or 321Algorithms" for any of the supported protocol 2 key types.
298"ssh-rsa".
299 322
300The agent will delete any private key matching the specified public key 323The agent will delete any private key matching the specified public key
301and return SSH_AGENT_SUCCESS. If no such key was found, the agent will 324and 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
366Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key 389Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
367Algorithms" for either of the supported key types: "ssh-dss" or 390Algorithms" for any of the supported protocol 2 key types.
368"ssh-rsa".
369 391
3702.6 Private key operations 3922.6 Private key operations
371 393
@@ -429,9 +451,9 @@ a protocol 2 key:
429 uint32 flags 451 uint32 flags
430 452
431Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key 453Where "key_blob" is encoded as per RFC 4253 section 6.6 "Public Key
432Algorithms" for either of the supported key types: "ssh-dss" or 454Algorithms" 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 455a bit-mask, but at present only one possible value is defined (see below
434is defined (see below for its meaning): 456for 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
7The SSH protocol currently supports a simple public key authentication 7The SSH protocol currently supports a simple public key authentication
8mechanism. Unlike other public key implementations, SSH eschews the 8mechanism. Unlike other public key implementations, SSH eschews the use
9use of X.509 certificates and uses raw keys. This approach has some 9of X.509 certificates and uses raw keys. This approach has some benefits
10benefits relating to simplicity of configuration and minimisation 10relating to simplicity of configuration and minimisation of attack
11of attack surface, but it does not support the important use-cases 11surface, but it does not support the important use-cases of centrally
12of centrally managed, passwordless authentication and centrally 12managed, passwordless authentication and centrally certified host keys.
13certified host keys.
14 13
15These protocol extensions build on the simple public key authentication 14These protocol extensions build on the simple public key authentication
16system already in SSH to allow certificate-based authentication. 15system already in SSH to allow certificate-based authentication. The
17The certificates used are not traditional X.509 certificates, with 16certificates used are not traditional X.509 certificates, with numerous
18numerous options and complex encoding rules, but something rather 17options and complex encoding rules, but something rather more minimal: a
19more minimal: a key, some identity information and usage options 18key, some identity information and usage options that have been signed
20that have been signed with some other trusted key. 19with some other trusted key.
21 20
22A sshd server may be configured to allow authentication via certified 21A sshd server may be configured to allow authentication via certified
23keys, by extending the existing ~/.ssh/authorized_keys mechanism 22keys, by extending the existing ~/.ssh/authorized_keys mechanism to
24to allow specification of certification authority keys in addition 23allow specification of certification authority keys in addition to
25to raw user keys. The ssh client will support automatic verification 24raw user keys. The ssh client will support automatic verification of
26of acceptance of certified host keys, by adding a similar ability 25acceptance of certified host keys, by adding a similar ability to
27to specify CA keys in ~/.ssh/known_hosts. 26specify CA keys in ~/.ssh/known_hosts.
28 27
29Certified keys are represented using two new key types: 28Certified keys are represented using new key types:
30ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com that 29
31include certification information along with the public key that is used 30 ssh-rsa-cert-v01@openssh.com
32to 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
36These include certification information along with the public key
37that is used to sign challenges. ssh-keygen performs the CA signing
38operation.
33 39
34Protocol extensions 40Protocol extensions
35------------------- 41-------------------
@@ -47,10 +53,9 @@ in RFC4252 section 7.
47New public key formats 53New public key formats
48---------------------- 54----------------------
49 55
50The ssh-rsa-cert-v01@openssh.com and ssh-dss-cert-v01@openssh.com key 56The certificate key types take a similar high-level format (note: data
51types take a similar high-level format (note: data types and 57types and encoding are as per RFC4251 section 5). The serialised wire
52encoding are as per RFC4251 section 5). The serialised wire encoding of 58encoding of these certificates is also used for storing them on disk.
53these 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
101ECDSA 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
96The nonce field is a CA-provided random bitstring of arbitrary length 121The 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
98inducing collisions in the signature hash infeasible. 123inducing collisions in the signature hash infeasible.
@@ -101,6 +126,9 @@ e and n are the RSA exponent and public modulus respectively.
101 126
102p, q, g, y are the DSA parameters as described in FIPS-186-2. 127p, q, g, y are the DSA parameters as described in FIPS-186-2.
103 128
129curve and public key are respectively the ECDSA "[identifier]" and "Q"
130defined in section 3.1 of RFC5656.
131
104serial is an optional certificate serial number set by the CA to 132serial is an optional certificate serial number set by the CA to
105provide an abbreviated way to refer to certificates from that CA. 133provide an abbreviated way to refer to certificates from that CA.
106If a CA does not wish to number its certificates it must set this 134If 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
124certificate. Each represents a time in seconds since 1970-01-01 152certificate. Each represents a time in seconds since 1970-01-01
12500:00:00. A certificate is considered valid if: 15300: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
128criticial options is a set of zero or more key options encoded as 157criticial options is a set of zero or more key options encoded as
129below. All such options are "critical" in the sense that an implementation 158below. 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
137the protocol. 166the protocol.
138 167
139signature key contains the CA key used to sign the certificate. 168signature key contains the CA key used to sign the certificate.
140The valid key types for CA keys are ssh-rsa and ssh-dss. "Chained" 169The valid key types for CA keys are ssh-rsa, ssh-dss and the ECDSA types
170ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521. "Chained"
141certificates, where the signature key type is a certificate type itself 171certificates, where the signature key type is a certificate type itself
142are NOT supported. Note that it is possible for a RSA certificate key to 172are NOT supported. Note that it is possible for a RSA certificate key to
143be signed by a DSS CA key and vice-versa. 173be signed by a DSS or ECDSA CA key and vice-versa.
144 174
145signature is computed over all preceding fields from the initial string 175signature is computed over all preceding fields from the initial string
146up to, and including the signature key. Signatures are computed and 176up to, and including the signature key. Signatures are computed and
147encoded according to the rules defined for the CA's public key algorithm 177encoded 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
179types).
149 180
150Critical options 181Critical 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 }
diff --git a/authfd.c b/authfd.c
index 739722fbf..ec537d2e9 100644
--- a/authfd.c
+++ b/authfd.c
@@ -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 */
44int
45buffer_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
82void
83buffer_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
90int
91buffer_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
133void
134buffer_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
diff --git a/buffer.h b/buffer.h
index 93baae2c8..1fb3f1666 100644
--- a/buffer.h
+++ b/buffer.h
@@ -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 *);
86void *buffer_get_string_ptr_ret(Buffer *, u_int *); 86void *buffer_get_string_ptr_ret(Buffer *, u_int *);
87int buffer_get_char_ret(char *, Buffer *); 87int buffer_get_char_ret(char *, Buffer *);
88 88
89#include <openssl/ec.h>
90
91int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *);
92void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *);
93int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *);
94void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *);
95
89#endif /* BUFFER_H */ 96#endif /* BUFFER_H */
diff --git a/dns.c b/dns.c
index 2e7bb5aae..131cb3d8b 100644
--- a/dns.c
+++ b/dns.c
@@ -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 }
diff --git a/kex.c b/kex.c
index ca5aae3e4..abe9b9f5d 100644
--- a/kex.c
+++ b/kex.c
@@ -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)
563void 567void
564dump_digest(char *msg, u_char *digest, int len) 568dump_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++) {
diff --git a/kex.h b/kex.h
index 62fa2ea50..a183ffda2 100644
--- a/kex.h
+++ b/kex.h
@@ -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 *);
145void kexdh_server(Kex *); 149void kexdh_server(Kex *);
146void kexgex_client(Kex *); 150void kexgex_client(Kex *);
147void kexgex_server(Kex *); 151void kexgex_server(Kex *);
152void kexecdh_client(Kex *);
153void kexecdh_server(Kex *);
148 154
149void 155void
150kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, 156kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int,
@@ -153,11 +159,17 @@ void
153kexgex_hash(const EVP_MD *, char *, char *, char *, int, char *, 159kexgex_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 *);
162void
163kex_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
167int kex_ecdh_name_to_nid(const char *);
156 168
157void 169void
158derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); 170derive_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)
161void dump_digest(char *, u_char *, int); 173void 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
44int
45kex_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
58void
59kex_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
45void
46kexecdh_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
47void
48kexecdh_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}
diff --git a/key.c b/key.c
index aed4678cb..842280a9f 100644
--- a/key.c
+++ b/key.c
@@ -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)
241int 257int
242key_equal_public(const Key *a, const Key *b) 258key_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
838const char * 909static const char *
839key_ssh_name(const Key *k) 910key_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
953const char *
954key_ssh_name(const Key *k)
955{
956 return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
957}
958
959const char *
960key_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
858u_int 966u_int
859key_size(const Key *k) 967key_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
1021int
1022key_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 */
1040int
1041key_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
1070static EC_KEY*
1071ecdsa_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
900Key * 1084Key *
901key_generate(int type, u_int bits) 1085key_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
1028int 1234int
1235key_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
1251int
1029key_names_valid2(const char *names) 1252key_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 *
1186key_from_blob(const u_char *blob, u_int blen) 1410key_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 */
1483int 1788int
1484key_certify(Key *k, Key *ca) 1789key_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
1964int
1965key_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
1978const char *
1979key_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
1992int
1993key_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
2077int
2078key_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)
2118void
2119key_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
2146void
2147key_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
diff --git a/key.h b/key.h
index 11d30eae6..2eb124364 100644
--- a/key.h
+++ b/key.h
@@ -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
33typedef struct Key Key; 34typedef struct Key Key;
34enum types { 35enum 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 **);
105int key_cert_is_legacy(Key *); 110int key_cert_is_legacy(Key *);
106 111
112int key_ecdsa_nid_from_name(const char *);
113int key_curve_name_to_nid(const char *);
114const char * key_curve_nid_to_name(int);
115int key_ecdsa_bits_to_nid(int);
116int key_ecdsa_group_to_nid(const EC_GROUP *);
117int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
118int key_ec_validate_private(const EC_KEY *);
119
107Key *key_from_blob(const u_char *, u_int); 120Key *key_from_blob(const u_char *, u_int);
108int key_to_blob(const Key *, u_char **, u_int *); 121int key_to_blob(const Key *, u_char **, u_int *);
109const char *key_ssh_name(const Key *); 122const char *key_ssh_name(const Key *);
123const char *key_ssh_name_plain(const Key *);
110int key_names_valid2(const char *); 124int key_names_valid2(const char *);
111 125
112int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 126int 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
115int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 129int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
116int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 130int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
131int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
132int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
117int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 133int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
118int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 134int 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)
137void key_dump_ec_point(const EC_GROUP *, const EC_POINT *);
138void key_dump_ec_key(const EC_KEY *);
139#endif
140
120#endif 141#endif
diff --git a/monitor.c b/monitor.c
index 9eb4e35c9..32395ee44 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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," \
diff --git a/packet.c b/packet.c
index 49aa97335..a06c5e3ef 100644
--- a/packet.c
+++ b/packet.c
@@ -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
644void
645packet_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
1520void
1521packet_get_ecpoint(const EC_GROUP *curve, EC_POINT *point)
1522{
1523 buffer_get_ecpoint(&active_state->incoming_packet, curve, point);
1524}
1525
1514void * 1526void *
1515packet_get_raw(u_int *length_ptr) 1527packet_get_raw(u_int *length_ptr)
1516{ 1528{
diff --git a/packet.h b/packet.h
index fd0b056fd..827561cdb 100644
--- a/packet.h
+++ b/packet.h
@@ -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
23void packet_set_connection(int, int); 24void packet_set_connection(int, int);
24void packet_set_timeout(int, int); 25void packet_set_timeout(int, int);
@@ -42,6 +43,7 @@ void packet_put_int(u_int value);
42void packet_put_int64(u_int64_t value); 43void packet_put_int64(u_int64_t value);
43void packet_put_bignum(BIGNUM * value); 44void packet_put_bignum(BIGNUM * value);
44void packet_put_bignum2(BIGNUM * value); 45void packet_put_bignum2(BIGNUM * value);
46void packet_put_ecpoint(const EC_GROUP *, const EC_POINT *);
45void packet_put_string(const void *buf, u_int len); 47void packet_put_string(const void *buf, u_int len);
46void packet_put_cstring(const char *str); 48void packet_put_cstring(const char *str);
47void packet_put_raw(const void *buf, u_int len); 49void packet_put_raw(const void *buf, u_int len);
@@ -59,6 +61,7 @@ u_int packet_get_int(void);
59u_int64_t packet_get_int64(void); 61u_int64_t packet_get_int64(void);
60void packet_get_bignum(BIGNUM * value); 62void packet_get_bignum(BIGNUM * value);
61void packet_get_bignum2(BIGNUM * value); 63void packet_get_bignum2(BIGNUM * value);
64void packet_get_ecpoint(const EC_GROUP *, EC_POINT *);
62void *packet_get_raw(u_int *length_ptr); 65void *packet_get_raw(u_int *length_ptr);
63void *packet_get_string(u_int *length_ptr); 66void *packet_get_string(u_int *length_ptr);
64char *packet_get_cstring(u_int *length_ptr); 67char *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)
diff --git a/ssh-add.1 b/ssh-add.1
index d7cc53101..3699db5eb 100644
--- a/ssh-add.1
+++ b/ssh-add.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
57adds RSA or DSA identities to the authentication agent, 57adds private key identities to the authentication agent,
58.Xr ssh-agent 1 . 58.Xr ssh-agent 1 .
59When run without arguments, it adds the files 59When 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
62and 63and
63.Pa ~/.ssh/identity . 64.Pa ~/.ssh/identity .
64After loading a private key, 65After loading a private key,
@@ -165,6 +166,8 @@ socket used to communicate with the agent.
165Contains the protocol version 1 RSA authentication identity of the user. 166Contains the protocol version 1 RSA authentication identity of the user.
166.It Pa ~/.ssh/id_dsa 167.It Pa ~/.ssh/id_dsa
167Contains the protocol version 2 DSA authentication identity of the user. 168Contains the protocol version 2 DSA authentication identity of the user.
169.It Pa ~/.ssh/id_ecdsa
170Contains the protocol version 2 ECDSA authentication identity of the user.
168.It Pa ~/.ssh/id_rsa 171.It Pa ~/.ssh/id_rsa
169Contains the protocol version 2 RSA authentication identity of the user. 172Contains the protocol version 2 RSA authentication identity of the user.
170.El 173.El
diff --git a/ssh-add.c b/ssh-add.c
index 7f8fb2c6d..31e618390 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -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;
70static char *default_files[] = { 70static 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
55is a program to hold private keys used for public key authentication 55is a program to hold private keys used for public key authentication
56(RSA, DSA). 56(RSA, DSA, ECDSA).
57The idea is that 57The idea is that
58.Nm 58.Nm
59is started in the beginning of an X-session or a login session, and 59is 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
115adds the files 115adds 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
118and 119and
119.Pa ~/.ssh/identity . 120.Pa ~/.ssh/identity .
120If the identity has a passphrase, 121If the identity has a passphrase,
@@ -187,6 +188,8 @@ line terminates.
187Contains the protocol version 1 RSA authentication identity of the user. 188Contains the protocol version 1 RSA authentication identity of the user.
188.It Pa ~/.ssh/id_dsa 189.It Pa ~/.ssh/id_dsa
189Contains the protocol version 2 DSA authentication identity of the user. 190Contains the protocol version 2 DSA authentication identity of the user.
191.It Pa ~/.ssh/id_ecdsa
192Contains the protocol version 2 ECDSA authentication identity of the user.
190.It Pa ~/.ssh/id_rsa 193.It Pa ~/.ssh/id_rsa
191Contains the protocol version 2 RSA authentication identity of the user. 194Contains 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
42int
43ssh_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}
90int
91ssh_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 @@
125generates, manages and converts authentication keys for 125generates, manages and converts authentication keys for
126.Xr ssh 1 . 126.Xr ssh 1 .
127.Nm 127.Nm
128can create RSA keys for use by SSH protocol version 1 and RSA or DSA 128can create RSA keys for use by SSH protocol version 1 and RSA, DSA or ECDSA
129keys for use by SSH protocol version 2. 129keys for use by SSH protocol version 2.
130The type of key to be generated is specified with the 130The type of key to be generated is specified with the
131.Fl t 131.Fl t
@@ -142,9 +142,10 @@ See the
142section for details. 142section for details.
143.Pp 143.Pp
144Normally each user wishing to use SSH 144Normally each user wishing to use SSH
145with RSA or DSA authentication runs this once to create the authentication 145with public key authentication runs this once to create the authentication
146key in 146key in
147.Pa ~/.ssh/identity , 147.Pa ~/.ssh/identity ,
148.Pa ~/.ssh/id_ecdsa ,
148.Pa ~/.ssh/id_dsa 149.Pa ~/.ssh/id_dsa
149or 150or
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
60u_int32_t bits = 0; 61u_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.
88The possible values are 88The possible values are
89.Dq rsa1 89.Dq rsa1
90for protocol version 1 and 90for protocol version 1 and
91.Dq rsa 91.Dq dsa ,
92.Dq ecdsa
92or 93or
93.Dq dsa 94.Dq rsa
94for protocol version 2. 95for protocol version 2.
95Multiple values may be specified by separating them with commas. 96Multiple values may be specified by separating them with commas.
96The default is 97The default is
@@ -122,7 +123,7 @@ attacks which have begun after the ssh_known_hosts file was created.
122host-or-namelist bits exponent modulus 123host-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
127host-or-namelist keytype base64-encoded-key 128host-or-namelist keytype base64-encoded-key
128.Ed 129.Ed
@@ -130,9 +131,12 @@ host-or-namelist keytype base64-encoded-key
130Where 131Where
131.Pa keytype 132.Pa keytype
132is either 133is either
133.Dq ssh-rsa 134.Dq ecdsa-sha2-nistp256 ,
135.Dq ecdsa-sha2-nistp384 ,
136.Dq ecdsa-sha2-nistp521 ,
137.Dq ssh-dss
134or 138or
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
149which have new or different keys from those in the sorted file 153which 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
53int ssh_port = SSH_DEFAULT_PORT; 53int 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
59int get_keytypes = KT_RSA; /* Get only RSA keys by default */ 60int 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
62is enabled. 62is 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
66These files contain the private parts of the host keys used to 67These files contain the private parts of the host keys used to
67generate the digital signature. 68generate the digital signature.
@@ -72,6 +73,7 @@ Since they are readable only by root,
72must be set-uid root if host-based authentication is used. 73must 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
76If these files exist they are assumed to contain public certificate 78If these files exist they are assumed to contain public certificate
77information corresponding with the private keys above. 79information corresponding with the private keys above.
diff --git a/ssh.1 b/ssh.1
index 9b134f4ba..a3d001152 100644
--- a/ssh.1
+++ b/ssh.1
@@ -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
269private RSA key. 269private RSA key.
270.It Fl i Ar identity_file 270.It Fl i Ar identity_file
271Selects a file from which the identity (private key) for 271Selects a file from which the identity (private key) for
272RSA or DSA authentication is read. 272public key authentication is read.
273The default is 273The default is
274.Pa ~/.ssh/identity 274.Pa ~/.ssh/identity
275for protocol version 1, and 275for protocol version 1, and
276.Pa ~/.ssh/id_rsa 276.Pa ~/.ssh/id_dsa ,
277.Pa ~/.ssh/id_ecdsa
277and 278and
278.Pa ~/.ssh/id_dsa 279.Pa ~/.ssh/id_rsa
279for protocol version 2. 280for protocol version 2.
280Identity files may also be specified on 281Identity files may also be specified on
281a per-host basis in the configuration file. 282a per-host basis in the configuration file.
@@ -721,9 +722,9 @@ key pair for authentication purposes.
721The server knows the public key, and only the user knows the private key. 722The server knows the public key, and only the user knows the private key.
722.Nm 723.Nm
723implements public key authentication protocol automatically, 724implements public key authentication protocol automatically,
724using either the RSA or DSA algorithms. 725using one of the DSA, ECDSA or RSA algorithms.
725Protocol 1 is restricted to using only RSA keys, 726Protocol 1 is restricted to using only RSA keys,
726but protocol 2 may use either. 727but protocol 2 may use any.
727The 728The
728.Sx HISTORY 729.Sx HISTORY
729section of 730section 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),
751or 754or
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),
759or 764or
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,
1277and not accessible by others. 1282and not accessible by others.
1278.Pp 1283.Pp
1279.It Pa ~/.ssh/authorized_keys 1284.It Pa ~/.ssh/authorized_keys
1280Lists the public keys (RSA/DSA) that can be used for logging in as this user. 1285Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in as
1286this user.
1281The format of this file is described in the 1287The format of this file is described in the
1282.Xr sshd 8 1288.Xr sshd 8
1283manual page. 1289manual 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
1302Contains the private key for authentication. 1309Contains the private key for authentication.
1303These files 1310These 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
1315Contains the public key for authentication. 1323Contains the public key for authentication.
1316These files are not 1324These 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
1353These three files contain the private parts of the host keys 1362These three files contain the private parts of the host keys
1354and are used for host-based authentication. 1363and are used for host-based authentication.
diff --git a/ssh.c b/ssh.c
index 44b570bf9..1cdfc58e3 100644
--- a/ssh.c
+++ b/ssh.c
@@ -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 }
diff --git a/ssh2.h b/ssh2.h
index 3ffaf686b..51a963cae 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -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
547Specifies the protocol version 2 host key algorithms 547Specifies the protocol version 2 host key algorithms
548that the client wants to use in order of preference. 548that the client wants to use in order of preference.
549The default for this option is: 549The default for this option is:
550.Dq ssh-rsa,ssh-dss . 550.Bd -literal -offset 3n
551ecdsa-sha2-nistp256-cert-v01@openssh.com,
552ecdsa-sha2-nistp384-cert-v01@openssh.com,
553ecdsa-sha2-nistp521-cert-v01@openssh.com,
554ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,
555ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,
556ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
557ssh-rsa,ssh-dss
558.Ed
551.It Cm HostKeyAlias 559.It Cm HostKeyAlias
552Specifies an alias that should be used instead of the 560Specifies an alias that should be used instead of the
553real host name when looking up or saving the host key 561real host name when looking up or saving the host key
@@ -583,14 +591,15 @@ offers many different identities.
583The default is 591The default is
584.Dq no . 592.Dq no .
585.It Cm IdentityFile 593.It Cm IdentityFile
586Specifies a file from which the user's RSA or DSA authentication identity 594Specifies a file from which the user's DSA, ECDSA or DSA authentication
587is read. 595identity is read.
588The default is 596The default is
589.Pa ~/.ssh/identity 597.Pa ~/.ssh/identity
590for protocol version 1, and 598for protocol version 1, and
591.Pa ~/.ssh/id_rsa 599.Pa ~/.ssh/id_dsa ,
600.Pa ~/.ssh/id_ecdsa
592and 601and
593.Pa ~/.ssh/id_dsa 602.Pa ~/.ssh/id_rsa
594for protocol version 2. 603for protocol version 2.
595Additionally, any identities represented by the authentication agent 604Additionally, any identities represented by the authentication agent
596will be used for authentication. 605will 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)
1173static int 1173static int
1174show_other_keys(const char *host, Key *key) 1174show_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;
diff --git a/sshd.8 b/sshd.8
index bf9d6a2ec..9d2efc7e1 100644
--- a/sshd.8
+++ b/sshd.8
@@ -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).
170The default is 170The default is
171.Pa /etc/ssh/ssh_host_key 171.Pa /etc/ssh/ssh_host_key
172for protocol version 1, and 172for 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
174and 175and
175.Pa /etc/ssh/ssh_host_dsa_key 176.Pa /etc/ssh/ssh_host_rsa_key
176for protocol version 2. 177for protocol version 2.
177It is possible to have multiple host key files for 178It is possible to have multiple host key files for
178the different protocol versions and host key algorithms. 179the different protocol versions and host key algorithms.
@@ -275,7 +276,7 @@ though this can be changed via the
275.Cm Protocol 276.Cm Protocol
276option in 277option in
277.Xr sshd_config 5 . 278.Xr sshd_config 5 .
278Protocol 2 supports both RSA and DSA keys; 279Protocol 2 supports DSA, ECDSA and RSA keys;
279protocol 1 only supports RSA keys. 280protocol 1 only supports RSA keys.
280For both protocols, 281For both protocols,
281each host has a host-specific key, 282each host has a host-specific key,
@@ -483,6 +484,9 @@ protocol version 1; the
483comment field is not used for anything (but may be convenient for the 484comment field is not used for anything (but may be convenient for the
484user to identify the key). 485user to identify the key).
485For protocol version 2 the keytype is 486For 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
487or 491or
488.Dq ssh-rsa . 492.Dq ssh-rsa .
@@ -494,6 +498,7 @@ keys up to 16 kilobits.
494You don't want to type them in; instead, copy the 498You 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 ,
497or the 502or the
498.Pa id_rsa.pub 503.Pa id_rsa.pub
499file and edit it. 504file and edit it.
@@ -792,7 +797,8 @@ secret, but the recommended permissions are read/write/execute for the user,
792and not accessible by others. 797and not accessible by others.
793.Pp 798.Pp
794.It Pa ~/.ssh/authorized_keys 799.It Pa ~/.ssh/authorized_keys
795Lists the public keys (RSA/DSA) that can be used for logging in as this user. 800Lists the public keys (DSA/ECDSA/RSA) that can be used for logging in
801as this user.
796The format of this file is described above. 802The format of this file is described above.
797The content of the file is not highly sensitive, but the recommended 803The content of the file is not highly sensitive, but the recommended
798permissions are read/write for the user, and not accessible by others. 804permissions 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
875These three files contain the private parts of the host keys. 882These three files contain the private parts of the host keys.
876These files should only be owned by root, readable only by root, and not 883These 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
885These three files contain the public parts of the host keys. 893These three files contain the public parts of the host keys.
886These files should be world-readable but writable only by 894These files should be world-readable but writable only by
diff --git a/sshd.c b/sshd.c
index 52a3789bb..658a4978d 100644
--- a/sshd.c
+++ b/sshd.c
@@ -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.
470The default is 470The default is
471.Pa /etc/ssh/ssh_host_key 471.Pa /etc/ssh/ssh_host_key
472for protocol version 1, and 472for 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
474and 475and
475.Pa /etc/ssh/ssh_host_dsa_key 476.Pa /etc/ssh/ssh_host_rsa_key
476for protocol version 2. 477for protocol version 2.
477Note that 478Note 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.
480It is possible to have multiple host key files. 481It is possible to have multiple host key files.
481.Dq rsa1 482.Dq rsa1
482keys are used for version 1 and 483keys are used for version 1 and
483.Dq dsa 484.Dq dsa ,
485.Dq ecdsa
484or 486or
485.Dq rsa 487.Dq rsa
486are used for version 2 of the SSH protocol. 488are 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
74void 74void
75dump_base64(FILE *fp, u_char *data, u_int len) 75dump_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
27int uuencode(const u_char *, u_int, char *, size_t); 27int uuencode(const u_char *, u_int, char *, size_t);
28int uudecode(const char *, u_char *, size_t); 28int uudecode(const char *, u_char *, size_t);
29void dump_base64(FILE *, u_char *, u_int); 29void dump_base64(FILE *, const u_char *, u_int);