1323124Sdes/* $OpenBSD: key.c,v 1.130 2016/05/02 09:36:42 djm Exp $ */
258582Skris/*
3295367Sdes * placed in the public domain
458582Skris */
5162856Sdes
676262Sgreen#include "includes.h"
758582Skris
8162856Sdes#include <sys/types.h>
9295367Sdes#include <errno.h>
10162856Sdes#include <stdarg.h>
11162856Sdes#include <stdio.h>
12295367Sdes#include <limits.h>
13162856Sdes
14295367Sdes#define SSH_KEY_NO_DEFINE
1558582Skris#include "key.h"
16295367Sdes
17295367Sdes#include "compat.h"
18295367Sdes#include "sshkey.h"
19295367Sdes#include "ssherr.h"
2076262Sgreen#include "log.h"
21295367Sdes#include "authfile.h"
2258582Skris
23204917Sdesvoid
24204917Sdeskey_add_private(Key *k)
2576262Sgreen{
26295367Sdes	int r;
27295367Sdes
28295367Sdes	if ((r = sshkey_add_private(k)) != 0)
29295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
30204917Sdes}
31204917Sdes
32204917SdesKey *
33204917Sdeskey_new_private(int type)
34204917Sdes{
35295367Sdes	Key *ret = NULL;
36204917Sdes
37295367Sdes	if ((ret = sshkey_new_private(type)) == NULL)
38295367Sdes		fatal("%s: failed", __func__);
39295367Sdes	return ret;
4076262Sgreen}
4199063Sdes
4258582Skrisint
4360576Skriskey_read(Key *ret, char **cpp)
4458582Skris{
45295367Sdes	return sshkey_read(ret, cpp) == 0 ? 1 : -1;
4658582Skris}
4799063Sdes
4858582Skrisint
49126277Sdeskey_write(const Key *key, FILE *f)
5058582Skris{
51295367Sdes	return sshkey_write(key, f) == 0 ? 1 : 0;
5258582Skris}
5399063Sdes
54295367SdesKey *
55295367Sdeskey_generate(int type, u_int bits)
56207319Sdes{
57295367Sdes	int r;
58295367Sdes	Key *ret = NULL;
59207319Sdes
60295367Sdes	if ((r = sshkey_generate(type, bits, &ret)) != 0)
61295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
62255767Sdes	return ret;
63255767Sdes}
64255767Sdes
65204917Sdesvoid
66295367Sdeskey_cert_copy(const Key *from_key, Key *to_key)
67204917Sdes{
68295367Sdes	int r;
69204917Sdes
70295367Sdes	if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
71295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
72204917Sdes}
73204917Sdes
7476262SgreenKey *
75126277Sdeskey_from_private(const Key *k)
7676262Sgreen{
77295367Sdes	int r;
78295367Sdes	Key *ret = NULL;
7976262Sgreen
80295367Sdes	if ((r = sshkey_from_private(k, &ret)) != 0)
81295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
82204917Sdes	return ret;
83204917Sdes}
84204917Sdes
85295367Sdesstatic void
86295367Sdesfatal_on_fatal_errors(int r, const char *func, int extra_fatal)
8776262Sgreen{
88295367Sdes	if (r == SSH_ERR_INTERNAL_ERROR ||
89295367Sdes	    r == SSH_ERR_ALLOC_FAIL ||
90295367Sdes	    (extra_fatal != 0 && r == extra_fatal))
91295367Sdes		fatal("%s: %s", func, ssh_err(r));
9276262Sgreen}
9376262Sgreen
94262566SdesKey *
95262566Sdeskey_from_blob(const u_char *blob, u_int blen)
96262566Sdes{
97295367Sdes	int r;
98295367Sdes	Key *ret = NULL;
99295367Sdes
100295367Sdes	if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
101295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
102295367Sdes		error("%s: %s", __func__, ssh_err(r));
103295367Sdes		return NULL;
104295367Sdes	}
105295367Sdes	return ret;
106262566Sdes}
107262566Sdes
108295367Sdesint
109295367Sdeskey_to_blob(const Key *key, u_char **blobp, u_int *lenp)
11076262Sgreen{
111295367Sdes	u_char *blob;
112295367Sdes	size_t blen;
113295367Sdes	int r;
11476262Sgreen
115262566Sdes	if (blobp != NULL)
116262566Sdes		*blobp = NULL;
117262566Sdes	if (lenp != NULL)
118262566Sdes		*lenp = 0;
119295367Sdes	if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
120295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
121295367Sdes		error("%s: %s", __func__, ssh_err(r));
12276262Sgreen		return 0;
12376262Sgreen	}
124295367Sdes	if (blen > INT_MAX)
125295367Sdes		fatal("%s: giant len %zu", __func__, blen);
126295367Sdes	if (blobp != NULL)
127295367Sdes		*blobp = blob;
128106130Sdes	if (lenp != NULL)
129295367Sdes		*lenp = blen;
130295367Sdes	return blen;
13176262Sgreen}
13276262Sgreen
13376262Sgreenint
134295367Sdeskey_sign(const Key *key, u_char **sigp, u_int *lenp,
135296781Sdes    const u_char *data, u_int datalen, const char *alg)
136248619Sdes{
137295367Sdes	int r;
138295367Sdes	u_char *sig;
139295367Sdes	size_t siglen;
140248619Sdes
141295367Sdes	if (sigp != NULL)
142295367Sdes		*sigp = NULL;
143295367Sdes	if (lenp != NULL)
144295367Sdes		*lenp = 0;
145295367Sdes	if ((r = sshkey_sign(key, &sig, &siglen,
146296781Sdes	    data, datalen, alg, datafellows)) != 0) {
147295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
148295367Sdes		error("%s: %s", __func__, ssh_err(r));
14976262Sgreen		return -1;
15076262Sgreen	}
151295367Sdes	if (siglen > INT_MAX)
152295367Sdes		fatal("%s: giant len %zu", __func__, siglen);
153295367Sdes	if (sigp != NULL)
154295367Sdes		*sigp = sig;
155295367Sdes	if (lenp != NULL)
156295367Sdes		*lenp = siglen;
157295367Sdes	return 0;
15876262Sgreen}
15976262Sgreen
16076262Sgreenint
161295367Sdeskey_verify(const Key *key, const u_char *signature, u_int signaturelen,
162126277Sdes    const u_char *data, u_int datalen)
16376262Sgreen{
164295367Sdes	int r;
16592559Sdes
166295367Sdes	if ((r = sshkey_verify(key, signature, signaturelen,
167295367Sdes	    data, datalen, datafellows)) != 0) {
168295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
169295367Sdes		error("%s: %s", __func__, ssh_err(r));
170295367Sdes		return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
17176262Sgreen	}
172295367Sdes	return 1;
17376262Sgreen}
17498684Sdes
17598684SdesKey *
176126277Sdeskey_demote(const Key *k)
17798684Sdes{
178295367Sdes	int r;
179295367Sdes	Key *ret = NULL;
18098684Sdes
181295367Sdes	if ((r = sshkey_demote(k, &ret)) != 0)
182295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
183295367Sdes	return ret;
18498684Sdes}
185204917Sdes
186204917Sdesint
187295367Sdeskey_to_certified(Key *k)
188204917Sdes{
189295367Sdes	int r;
190204917Sdes
191295367Sdes	if ((r = sshkey_to_certified(k)) != 0) {
192295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
193295367Sdes		error("%s: %s", __func__, ssh_err(r));
194204917Sdes		return -1;
195204917Sdes	}
196295367Sdes	return 0;
197204917Sdes}
198204917Sdes
199204917Sdesint
200204917Sdeskey_drop_cert(Key *k)
201204917Sdes{
202295367Sdes	int r;
203295367Sdes
204295367Sdes	if ((r = sshkey_drop_cert(k)) != 0) {
205295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
206295367Sdes		error("%s: %s", __func__, ssh_err(r));
207204917Sdes		return -1;
208204917Sdes	}
209262566Sdes	return 0;
210204917Sdes}
211204917Sdes
212204917Sdesint
213204917Sdeskey_certify(Key *k, Key *ca)
214204917Sdes{
215295367Sdes	int r;
216204917Sdes
217323124Sdes	if ((r = sshkey_certify(k, ca, NULL)) != 0) {
218295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
219295367Sdes		error("%s: %s", __func__, ssh_err(r));
220204917Sdes		return -1;
221204917Sdes	}
222204917Sdes	return 0;
223204917Sdes}
224204917Sdes
225204917Sdesint
226204917Sdeskey_cert_check_authority(const Key *k, int want_host, int require_principal,
227204917Sdes    const char *name, const char **reason)
228204917Sdes{
229295367Sdes	int r;
230204917Sdes
231295367Sdes	if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
232295367Sdes	    name, reason)) != 0) {
233295367Sdes		fatal_on_fatal_errors(r, __func__, 0);
234295367Sdes		error("%s: %s", __func__, ssh_err(r));
235204917Sdes		return -1;
236204917Sdes	}
237204917Sdes	return 0;
238204917Sdes}
239215116Sdes
240295367Sdes#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
241215116Sdesint
242295367Sdeskey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
243215116Sdes{
244295367Sdes	int r;
245295367Sdes
246295367Sdes	if ((r = sshkey_ec_validate_public(group, public)) != 0) {
247295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
248295367Sdes		error("%s: %s", __func__, ssh_err(r));
249295367Sdes		return -1;
250215116Sdes	}
251295367Sdes	return 0;
252215116Sdes}
253221420Sdes
254221420Sdesint
255295367Sdeskey_ec_validate_private(const EC_KEY *key)
256221420Sdes{
257295367Sdes	int r;
258221420Sdes
259295367Sdes	if ((r = sshkey_ec_validate_private(key)) != 0) {
260295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
261295367Sdes		error("%s: %s", __func__, ssh_err(r));
262295367Sdes		return -1;
263295367Sdes	}
264295367Sdes	return 0;
265221420Sdes}
266295367Sdes#endif /* WITH_OPENSSL */
267221420Sdes
268295367Sdesvoid
269295367Sdeskey_private_serialize(const Key *key, struct sshbuf *b)
270221420Sdes{
271295367Sdes	int r;
272295367Sdes
273295367Sdes	if ((r = sshkey_private_serialize(key, b)) != 0)
274295367Sdes		fatal("%s: %s", __func__, ssh_err(r));
275221420Sdes}
276221420Sdes
277295367SdesKey *
278295367Sdeskey_private_deserialize(struct sshbuf *blob)
279221420Sdes{
280295367Sdes	int r;
281295367Sdes	Key *ret = NULL;
282295367Sdes
283295367Sdes	if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
284295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
285295367Sdes		error("%s: %s", __func__, ssh_err(r));
286295367Sdes		return NULL;
287295367Sdes	}
288295367Sdes	return ret;
289221420Sdes}
290221420Sdes
291295367Sdes/* authfile.c */
292295367Sdes
293262566Sdesint
294295367Sdeskey_save_private(Key *key, const char *filename, const char *passphrase,
295295367Sdes    const char *comment, int force_new_format, const char *new_format_cipher,
296295367Sdes    int new_format_rounds)
297221420Sdes{
298295367Sdes	int r;
299221420Sdes
300295367Sdes	if ((r = sshkey_save_private(key, filename, passphrase, comment,
301295367Sdes	    force_new_format, new_format_cipher, new_format_rounds)) != 0) {
302295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
303295367Sdes		error("%s: %s", __func__, ssh_err(r));
304295367Sdes		return 0;
305295367Sdes	}
306295367Sdes	return 1;
307221420Sdes}
308221420Sdes
309221420Sdesint
310295367Sdeskey_load_file(int fd, const char *filename, struct sshbuf *blob)
311221420Sdes{
312295367Sdes	int r;
313221420Sdes
314295367Sdes	if ((r = sshkey_load_file(fd, blob)) != 0) {
315295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
316295367Sdes		error("%s: %s", __func__, ssh_err(r));
317295367Sdes		return 0;
318221420Sdes	}
319295367Sdes	return 1;
320295367Sdes}
321221420Sdes
322295367SdesKey *
323295367Sdeskey_load_cert(const char *filename)
324295367Sdes{
325295367Sdes	int r;
326295367Sdes	Key *ret = NULL;
327221420Sdes
328295367Sdes	if ((r = sshkey_load_cert(filename, &ret)) != 0) {
329295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
330295367Sdes		/* Old authfile.c ignored all file errors. */
331295367Sdes		if (r == SSH_ERR_SYSTEM_ERROR)
332295367Sdes			debug("%s: %s", __func__, ssh_err(r));
333295367Sdes		else
334295367Sdes			error("%s: %s", __func__, ssh_err(r));
335295367Sdes		return NULL;
336221420Sdes	}
337295367Sdes	return ret;
338221420Sdes
339221420Sdes}
340221420Sdes
341295367SdesKey *
342295367Sdeskey_load_public(const char *filename, char **commentp)
343221420Sdes{
344295367Sdes	int r;
345295367Sdes	Key *ret = NULL;
346221420Sdes
347295367Sdes	if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
348295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
349295367Sdes		/* Old authfile.c ignored all file errors. */
350295367Sdes		if (r == SSH_ERR_SYSTEM_ERROR)
351295367Sdes			debug("%s: %s", __func__, ssh_err(r));
352295367Sdes		else
353295367Sdes			error("%s: %s", __func__, ssh_err(r));
354295367Sdes		return NULL;
355221420Sdes	}
356221420Sdes	return ret;
357221420Sdes}
358221420Sdes
359295367SdesKey *
360295367Sdeskey_load_private(const char *path, const char *passphrase,
361295367Sdes    char **commentp)
362221420Sdes{
363295367Sdes	int r;
364295367Sdes	Key *ret = NULL;
365221420Sdes
366295367Sdes	if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
367295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
368295367Sdes		/* Old authfile.c ignored all file errors. */
369295367Sdes		if (r == SSH_ERR_SYSTEM_ERROR ||
370295367Sdes		    r == SSH_ERR_KEY_WRONG_PASSPHRASE)
371295367Sdes			debug("%s: %s", __func__, ssh_err(r));
372295367Sdes		else
373295367Sdes			error("%s: %s", __func__, ssh_err(r));
374295367Sdes		return NULL;
375221420Sdes	}
376295367Sdes	return ret;
377221420Sdes}
378221420Sdes
379295367SdesKey *
380295367Sdeskey_load_private_cert(int type, const char *filename, const char *passphrase,
381295367Sdes    int *perm_ok)
382221420Sdes{
383295367Sdes	int r;
384295367Sdes	Key *ret = NULL;
385221420Sdes
386295367Sdes	if ((r = sshkey_load_private_cert(type, filename, passphrase,
387295367Sdes	    &ret, perm_ok)) != 0) {
388295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
389295367Sdes		/* Old authfile.c ignored all file errors. */
390295367Sdes		if (r == SSH_ERR_SYSTEM_ERROR ||
391295367Sdes		    r == SSH_ERR_KEY_WRONG_PASSPHRASE)
392295367Sdes			debug("%s: %s", __func__, ssh_err(r));
393295367Sdes		else
394295367Sdes			error("%s: %s", __func__, ssh_err(r));
395295367Sdes		return NULL;
396262566Sdes	}
397295367Sdes	return ret;
398262566Sdes}
399262566Sdes
400262566SdesKey *
401295367Sdeskey_load_private_type(int type, const char *filename, const char *passphrase,
402295367Sdes    char **commentp, int *perm_ok)
403262566Sdes{
404295367Sdes	int r;
405295367Sdes	Key *ret = NULL;
406262566Sdes
407295367Sdes	if ((r = sshkey_load_private_type(type, filename, passphrase,
408295367Sdes	    &ret, commentp, perm_ok)) != 0) {
409295367Sdes		fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
410295367Sdes		/* Old authfile.c ignored all file errors. */
411295367Sdes		if (r == SSH_ERR_SYSTEM_ERROR ||
412295367Sdes		    (r == SSH_ERR_KEY_WRONG_PASSPHRASE))
413295367Sdes			debug("%s: %s", __func__, ssh_err(r));
414295367Sdes		else
415295367Sdes			error("%s: %s", __func__, ssh_err(r));
416262566Sdes		return NULL;
417262566Sdes	}
418295367Sdes	return ret;
419295367Sdes}
420262566Sdes
421295367Sdesint
422295367Sdeskey_perm_ok(int fd, const char *filename)
423295367Sdes{
424295367Sdes	return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
425262566Sdes}
426295367Sdes
427