1 /* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
4 * Redistribution and use in source and binary forms,
5 * with or without modification, are permitted provided
6 * that the following conditions are met:
8 * Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the
10 * following disclaimer.
12 * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
17 * Neither the name of the copyright holder nor the names
18 * of any other contributors may be used to endorse or
19 * promote products derived from this software without
20 * specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
38 #include "libssh2_priv.h"
40 /* Needed for struct iovec on some platforms */
50 static int libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION
* session
,
53 /* {{{ libssh2_hostkey_method_ssh_rsa_init
54 * Initialize the server hostkey working area with e/n pair
57 libssh2_hostkey_method_ssh_rsa_init(LIBSSH2_SESSION
* session
,
58 const unsigned char *hostkey_data
,
59 unsigned long hostkey_data_len
,
62 libssh2_rsa_ctx
*rsactx
;
63 const unsigned char *s
, *e
, *n
;
64 unsigned long len
, e_len
, n_len
;
66 (void) hostkey_data_len
;
69 libssh2_hostkey_method_ssh_rsa_dtor(session
, abstract
);
74 len
= libssh2_ntohu32(s
);
77 if (len
!= 7 || strncmp((char *) s
, "ssh-rsa", 7) != 0) {
82 e_len
= libssh2_ntohu32(s
);
87 n_len
= libssh2_ntohu32(s
);
92 if (_libssh2_rsa_new(&rsactx
, e
, e_len
, n
, n_len
, NULL
, 0,
93 NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0, NULL
, 0))
103 /* {{{ libssh2_hostkey_method_ssh_rsa_initPEM
104 * Load a Private Key from a PEM file
107 libssh2_hostkey_method_ssh_rsa_initPEM(LIBSSH2_SESSION
* session
,
108 const char *privkeyfile
,
109 unsigned const char *passphrase
,
112 libssh2_rsa_ctx
*rsactx
;
117 libssh2_hostkey_method_ssh_rsa_dtor(session
, abstract
);
121 fp
= fopen(privkeyfile
, "r");
126 ret
= _libssh2_rsa_new_private(&rsactx
, session
, fp
, passphrase
);
139 /* {{{ libssh2_hostkey_method_ssh_rsa_sign
140 * Verify signature created by remote
143 libssh2_hostkey_method_ssh_rsa_sig_verify(LIBSSH2_SESSION
* session
,
144 const unsigned char *sig
,
145 unsigned long sig_len
,
146 const unsigned char *m
,
147 unsigned long m_len
, void **abstract
)
149 libssh2_rsa_ctx
*rsactx
= (libssh2_rsa_ctx
*) (*abstract
);
152 /* Skip past keyname_len(4) + keyname(7){"ssh-rsa"} + signature_len(4) */
155 return _libssh2_rsa_sha1_verify(rsactx
, sig
, sig_len
, m
, m_len
);
160 /* {{{ libssh2_hostkey_method_ssh_rsa_signv
161 * Construct a signature from an array of vectors
164 libssh2_hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION
* session
,
165 unsigned char **signature
,
166 unsigned long *signature_len
,
167 unsigned long veccount
,
168 const struct iovec datavec
[],
171 libssh2_rsa_ctx
*rsactx
= (libssh2_rsa_ctx
*) (*abstract
);
174 unsigned char hash
[SHA_DIGEST_LENGTH
];
175 libssh2_sha1_ctx ctx
;
177 libssh2_sha1_init(&ctx
);
178 for(i
= 0; i
< veccount
; i
++) {
179 libssh2_sha1_update(ctx
, datavec
[i
].iov_base
, datavec
[i
].iov_len
);
181 libssh2_sha1_final(ctx
, hash
);
183 ret
= _libssh2_rsa_sha1_sign(session
, rsactx
, hash
, SHA_DIGEST_LENGTH
,
184 signature
, signature_len
);
194 /* {{{ libssh2_hostkey_method_ssh_rsa_dtor
195 * Shutdown the hostkey
198 libssh2_hostkey_method_ssh_rsa_dtor(LIBSSH2_SESSION
* session
, void **abstract
)
200 libssh2_rsa_ctx
*rsactx
= (libssh2_rsa_ctx
*) (*abstract
);
203 _libssh2_rsa_free(rsactx
);
212 static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_rsa
= {
215 libssh2_hostkey_method_ssh_rsa_init
,
216 libssh2_hostkey_method_ssh_rsa_initPEM
,
217 libssh2_hostkey_method_ssh_rsa_sig_verify
,
218 libssh2_hostkey_method_ssh_rsa_signv
,
220 libssh2_hostkey_method_ssh_rsa_dtor
,
222 #endif /* LIBSSH2_RSA */
229 static int libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION
* session
,
232 /* {{{ libssh2_hostkey_method_ssh_dss_init
233 * Initialize the server hostkey working area with p/q/g/y set
236 libssh2_hostkey_method_ssh_dss_init(LIBSSH2_SESSION
* session
,
237 const unsigned char *hostkey_data
,
238 unsigned long hostkey_data_len
,
241 libssh2_dsa_ctx
*dsactx
;
242 const unsigned char *p
, *q
, *g
, *y
, *s
;
243 unsigned long p_len
, q_len
, g_len
, y_len
, len
;
244 (void) hostkey_data_len
;
247 libssh2_hostkey_method_ssh_dss_dtor(session
, abstract
);
252 len
= libssh2_ntohu32(s
);
254 if (len
!= 7 || strncmp((char *) s
, "ssh-dss", 7) != 0) {
259 p_len
= libssh2_ntohu32(s
);
263 q_len
= libssh2_ntohu32(s
);
267 g_len
= libssh2_ntohu32(s
);
271 y_len
= libssh2_ntohu32(s
);
276 _libssh2_dsa_new(&dsactx
, p
, p_len
, q
, q_len
, g
, g_len
, y
, y_len
, NULL
, 0);
285 /* {{{ libssh2_hostkey_method_ssh_dss_initPEM
286 * Load a Private Key from a PEM file
289 libssh2_hostkey_method_ssh_dss_initPEM(LIBSSH2_SESSION
* session
,
290 const char *privkeyfile
,
291 unsigned const char *passphrase
,
294 libssh2_dsa_ctx
*dsactx
;
299 libssh2_hostkey_method_ssh_dss_dtor(session
, abstract
);
303 fp
= fopen(privkeyfile
, "r");
308 ret
= _libssh2_dsa_new_private(&dsactx
, session
, fp
, passphrase
);
321 /* {{{ libssh2_hostkey_method_ssh_dss_sign
322 * Verify signature created by remote
325 libssh2_hostkey_method_ssh_dss_sig_verify(LIBSSH2_SESSION
* session
,
326 const unsigned char *sig
,
327 unsigned long sig_len
,
328 const unsigned char *m
,
329 unsigned long m_len
, void **abstract
)
331 libssh2_dsa_ctx
*dsactx
= (libssh2_dsa_ctx
*) (*abstract
);
333 /* Skip past keyname_len(4) + keyname(7){"ssh-dss"} + signature_len(4) */
337 libssh2_error(session
, LIBSSH2_ERROR_PROTO
,
338 "Invalid DSS signature length", 0);
341 return _libssh2_dsa_sha1_verify(dsactx
, sig
, m
, m_len
);
346 /* {{{ libssh2_hostkey_method_ssh_dss_signv
347 * Construct a signature from an array of vectors
350 libssh2_hostkey_method_ssh_dss_signv(LIBSSH2_SESSION
* session
,
351 unsigned char **signature
,
352 unsigned long *signature_len
,
353 unsigned long veccount
,
354 const struct iovec datavec
[],
357 libssh2_dsa_ctx
*dsactx
= (libssh2_dsa_ctx
*) (*abstract
);
358 unsigned char hash
[SHA_DIGEST_LENGTH
];
359 libssh2_sha1_ctx ctx
;
362 *signature
= LIBSSH2_ALLOC(session
, 2 * SHA_DIGEST_LENGTH
);
367 *signature_len
= 2 * SHA_DIGEST_LENGTH
;
368 memset(*signature
, 0, 2 * SHA_DIGEST_LENGTH
);
370 libssh2_sha1_init(&ctx
);
371 for(i
= 0; i
< veccount
; i
++) {
372 libssh2_sha1_update(ctx
, datavec
[i
].iov_base
, datavec
[i
].iov_len
);
374 libssh2_sha1_final(ctx
, hash
);
376 if (_libssh2_dsa_sha1_sign(dsactx
, hash
, SHA_DIGEST_LENGTH
, *signature
)) {
377 LIBSSH2_FREE(session
, *signature
);
386 /* {{{ libssh2_hostkey_method_ssh_dss_dtor
387 * Shutdown the hostkey method
390 libssh2_hostkey_method_ssh_dss_dtor(LIBSSH2_SESSION
* session
, void **abstract
)
392 libssh2_dsa_ctx
*dsactx
= (libssh2_dsa_ctx
*) (*abstract
);
395 _libssh2_dsa_free(dsactx
);
404 static const LIBSSH2_HOSTKEY_METHOD libssh2_hostkey_method_ssh_dss
= {
407 libssh2_hostkey_method_ssh_dss_init
,
408 libssh2_hostkey_method_ssh_dss_initPEM
,
409 libssh2_hostkey_method_ssh_dss_sig_verify
,
410 libssh2_hostkey_method_ssh_dss_signv
,
412 libssh2_hostkey_method_ssh_dss_dtor
,
414 #endif /* LIBSSH2_DSA */
416 static const LIBSSH2_HOSTKEY_METHOD
*_libssh2_hostkey_methods
[] = {
418 &libssh2_hostkey_method_ssh_rsa
,
419 #endif /* LIBSSH2_RSA */
421 &libssh2_hostkey_method_ssh_dss
,
422 #endif /* LIBSSH2_DSA */
426 const LIBSSH2_HOSTKEY_METHOD
**
427 libssh2_hostkey_methods(void)
429 return _libssh2_hostkey_methods
;
432 /* {{{ libssh2_hostkey_hash
433 * Returns hash signature
434 * Returned buffer should NOT be freed
435 * Length of buffer is determined by hash type
436 * i.e. MD5 == 16, SHA1 == 20
438 LIBSSH2_API
const char *
439 libssh2_hostkey_hash(LIBSSH2_SESSION
* session
, int hash_type
)
443 case LIBSSH2_HOSTKEY_HASH_MD5
:
444 return (char *) session
->server_hostkey_md5
;
446 #endif /* LIBSSH2_MD5 */
447 case LIBSSH2_HOSTKEY_HASH_SHA1
:
448 return (char *) session
->server_hostkey_sha1
;