blob: c2b696af9f38939851692fc0daca1893bc45d563 [file] [log] [blame]
deraadt@openbsd.org087266e2015-01-20 23:14:00 +00001/* $OpenBSD: key.c,v 1.126 2015/01/20 23:14:00 deraadt Exp $ */
Damien Miller450a7a12000-03-26 13:04:51 +10002/*
Damien Miller86687062014-07-02 15:28:02 +10003 * placed in the public domain
Damien Miller450a7a12000-03-26 13:04:51 +10004 */
Damien Millerd7834352006-08-05 12:39:39 +10005
Damien Miller450a7a12000-03-26 13:04:51 +10006#include "includes.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +00007
Damien Millerd7834352006-08-05 12:39:39 +10008#include <sys/types.h>
Damien Miller86687062014-07-02 15:28:02 +10009#include <errno.h>
Damien Millerded319c2006-09-01 15:38:36 +100010#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100011#include <stdio.h>
deraadt@openbsd.org087266e2015-01-20 23:14:00 +000012#include <limits.h>
Damien Millere3476ed2006-07-24 14:13:33 +100013
Damien Miller86687062014-07-02 15:28:02 +100014#define SSH_KEY_NO_DEFINE
Damien Miller450a7a12000-03-26 13:04:51 +100015#include "key.h"
Damien Miller86687062014-07-02 15:28:02 +100016
17#include "compat.h"
18#include "sshkey.h"
19#include "ssherr.h"
Ben Lindstrom226cfa02001-01-22 05:34:40 +000020#include "log.h"
Damien Miller86687062014-07-02 15:28:02 +100021#include "authfile.h"
Ben Lindstrom836f0e92002-06-23 21:21:30 +000022
Damien Miller0a80ca12010-02-27 07:55:05 +110023void
24key_add_private(Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +110025{
Damien Miller86687062014-07-02 15:28:02 +100026 int r;
27
28 if ((r = sshkey_add_private(k)) != 0)
29 fatal("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +110030}
31
32Key *
33key_new_private(int type)
34{
Damien Miller86687062014-07-02 15:28:02 +100035 Key *ret = NULL;
Damien Miller0a80ca12010-02-27 07:55:05 +110036
Damien Miller86687062014-07-02 15:28:02 +100037 if ((ret = sshkey_new_private(type)) == NULL)
38 fatal("%s: failed", __func__);
39 return ret;
Damien Miller0a80ca12010-02-27 07:55:05 +110040}
41
Damien Miller37876e92003-05-15 10:19:46 +100042u_char*
djm@openbsd.org56d1c832014-12-21 22:27:55 +000043key_fingerprint_raw(const Key *k, int dgst_alg, u_int *dgst_raw_length)
Damien Miller450a7a12000-03-26 13:04:51 +100044{
Damien Miller86687062014-07-02 15:28:02 +100045 u_char *ret = NULL;
46 size_t dlen;
47 int r;
Damien Miller450a7a12000-03-26 13:04:51 +100048
Damien Miller86687062014-07-02 15:28:02 +100049 if (dgst_raw_length != NULL)
50 *dgst_raw_length = 0;
djm@openbsd.org56d1c832014-12-21 22:27:55 +000051 if ((r = sshkey_fingerprint_raw(k, dgst_alg, &ret, &dlen)) != 0)
Damien Miller86687062014-07-02 15:28:02 +100052 fatal("%s: %s", __func__, ssh_err(r));
53 if (dlen > INT_MAX)
54 fatal("%s: giant len %zu", __func__, dlen);
55 *dgst_raw_length = dlen;
56 return ret;
Damien Miller450a7a12000-03-26 13:04:51 +100057}
58
Damien Miller0bc1bd82000-11-13 22:57:25 +110059int
Damien Millereba71ba2000-04-29 23:57:08 +100060key_read(Key *ret, char **cpp)
Damien Miller450a7a12000-03-26 13:04:51 +100061{
Damien Miller86687062014-07-02 15:28:02 +100062 return sshkey_read(ret, cpp) == 0 ? 1 : -1;
Damien Miller450a7a12000-03-26 13:04:51 +100063}
Ben Lindstrom836f0e92002-06-23 21:21:30 +000064
Damien Miller450a7a12000-03-26 13:04:51 +100065int
Damien Millerf58b58c2003-11-17 21:18:23 +110066key_write(const Key *key, FILE *f)
Damien Miller450a7a12000-03-26 13:04:51 +100067{
Damien Miller86687062014-07-02 15:28:02 +100068 return sshkey_write(key, f) == 0 ? 1 : 0;
Damien Miller450a7a12000-03-26 13:04:51 +100069}
Ben Lindstrom836f0e92002-06-23 21:21:30 +000070
Damien Miller0bc1bd82000-11-13 22:57:25 +110071Key *
Ben Lindstrom46c16222000-12-22 01:43:59 +000072key_generate(int type, u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +110073{
Damien Miller86687062014-07-02 15:28:02 +100074 int r;
75 Key *ret = NULL;
76
77 if ((r = sshkey_generate(type, bits, &ret)) != 0)
78 fatal("%s: %s", __func__, ssh_err(r));
79 return ret;
Damien Miller0bc1bd82000-11-13 22:57:25 +110080}
81
Damien Miller0a80ca12010-02-27 07:55:05 +110082void
Damien Miller86687062014-07-02 15:28:02 +100083key_cert_copy(const Key *from_key, Key *to_key)
Damien Miller0a80ca12010-02-27 07:55:05 +110084{
Damien Miller86687062014-07-02 15:28:02 +100085 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +110086
Damien Miller86687062014-07-02 15:28:02 +100087 if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
88 fatal("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +110089}
90
Damien Miller0bc1bd82000-11-13 22:57:25 +110091Key *
Damien Millerf58b58c2003-11-17 21:18:23 +110092key_from_private(const Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +110093{
Damien Miller86687062014-07-02 15:28:02 +100094 int r;
95 Key *ret = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +110096
Damien Miller86687062014-07-02 15:28:02 +100097 if ((r = sshkey_from_private(k, &ret)) != 0)
98 fatal("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +110099 return ret;
100}
101
Damien Miller86687062014-07-02 15:28:02 +1000102static void
103fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100104{
Damien Miller86687062014-07-02 15:28:02 +1000105 if (r == SSH_ERR_INTERNAL_ERROR ||
106 r == SSH_ERR_ALLOC_FAIL ||
107 (extra_fatal != 0 && r == extra_fatal))
108 fatal("%s: %s", func, ssh_err(r));
Damien Miller0bc1bd82000-11-13 22:57:25 +1100109}
110
Damien Miller4a3a9d42013-10-30 22:19:47 +1100111Key *
112key_from_blob(const u_char *blob, u_int blen)
113{
Damien Miller86687062014-07-02 15:28:02 +1000114 int r;
115 Key *ret = NULL;
Damien Miller4a3a9d42013-10-30 22:19:47 +1100116
Damien Miller86687062014-07-02 15:28:02 +1000117 if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
118 fatal_on_fatal_errors(r, __func__, 0);
119 error("%s: %s", __func__, ssh_err(r));
120 return NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100121 }
Damien Miller86687062014-07-02 15:28:02 +1000122 return ret;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100123}
124
125int
Damien Millerf3747bf2013-01-18 11:44:04 +1100126key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
127{
Damien Miller86687062014-07-02 15:28:02 +1000128 u_char *blob;
129 size_t blen;
130 int r;
131
132 if (blobp != NULL)
133 *blobp = NULL;
134 if (lenp != NULL)
135 *lenp = 0;
136 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
137 fatal_on_fatal_errors(r, __func__, 0);
138 error("%s: %s", __func__, ssh_err(r));
139 return 0;
140 }
141 if (blen > INT_MAX)
142 fatal("%s: giant len %zu", __func__, blen);
143 if (blobp != NULL)
144 *blobp = blob;
145 if (lenp != NULL)
146 *lenp = blen;
147 return blen;
Damien Millerf3747bf2013-01-18 11:44:04 +1100148}
149
150int
Damien Miller86687062014-07-02 15:28:02 +1000151key_sign(const Key *key, u_char **sigp, u_int *lenp,
Damien Millerf58b58c2003-11-17 21:18:23 +1100152 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100153{
Damien Miller86687062014-07-02 15:28:02 +1000154 int r;
155 u_char *sig;
156 size_t siglen;
157
158 if (sigp != NULL)
159 *sigp = NULL;
160 if (lenp != NULL)
161 *lenp = 0;
162 if ((r = sshkey_sign(key, &sig, &siglen,
163 data, datalen, datafellows)) != 0) {
164 fatal_on_fatal_errors(r, __func__, 0);
165 error("%s: %s", __func__, ssh_err(r));
Damien Miller0bc1bd82000-11-13 22:57:25 +1100166 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100167 }
Damien Miller86687062014-07-02 15:28:02 +1000168 if (siglen > INT_MAX)
169 fatal("%s: giant len %zu", __func__, siglen);
170 if (sigp != NULL)
171 *sigp = sig;
172 if (lenp != NULL)
173 *lenp = siglen;
Damien Miller5be9d9e2013-12-07 11:24:01 +1100174 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100175}
176
Damien Miller86687062014-07-02 15:28:02 +1000177int
178key_verify(const Key *key, const u_char *signature, u_int signaturelen,
179 const u_char *data, u_int datalen)
180{
181 int r;
182
183 if ((r = sshkey_verify(key, signature, signaturelen,
184 data, datalen, datafellows)) != 0) {
185 fatal_on_fatal_errors(r, __func__, 0);
186 error("%s: %s", __func__, ssh_err(r));
187 return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
188 }
189 return 1;
190}
191
192Key *
193key_demote(const Key *k)
194{
195 int r;
196 Key *ret = NULL;
197
198 if ((r = sshkey_demote(k, &ret)) != 0)
199 fatal("%s: %s", __func__, ssh_err(r));
200 return ret;
201}
202
203int
204key_to_certified(Key *k, int legacy)
205{
206 int r;
207
208 if ((r = sshkey_to_certified(k, legacy)) != 0) {
209 fatal_on_fatal_errors(r, __func__, 0);
210 error("%s: %s", __func__, ssh_err(r));
211 return -1;
212 }
213 return 0;
214}
215
216int
217key_drop_cert(Key *k)
218{
219 int r;
220
221 if ((r = sshkey_drop_cert(k)) != 0) {
222 fatal_on_fatal_errors(r, __func__, 0);
223 error("%s: %s", __func__, ssh_err(r));
224 return -1;
225 }
226 return 0;
227}
228
Damien Miller0a80ca12010-02-27 07:55:05 +1100229int
230key_certify(Key *k, Key *ca)
231{
Damien Miller86687062014-07-02 15:28:02 +1000232 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +1100233
Damien Miller86687062014-07-02 15:28:02 +1000234 if ((r = sshkey_certify(k, ca)) != 0) {
235 fatal_on_fatal_errors(r, __func__, 0);
236 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100237 return -1;
238 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100239 return 0;
240}
241
242int
243key_cert_check_authority(const Key *k, int want_host, int require_principal,
244 const char *name, const char **reason)
245{
Damien Miller86687062014-07-02 15:28:02 +1000246 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +1100247
Damien Miller86687062014-07-02 15:28:02 +1000248 if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
249 name, reason)) != 0) {
250 fatal_on_fatal_errors(r, __func__, 0);
251 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100252 return -1;
253 }
Damien Miller86687062014-07-02 15:28:02 +1000254 return 0;
255}
256
Darren Tuckerd1a04212014-07-19 07:23:55 +1000257#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
Damien Miller86687062014-07-02 15:28:02 +1000258int
259key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
260{
261 int r;
262
263 if ((r = sshkey_ec_validate_public(group, public)) != 0) {
264 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
265 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100266 return -1;
267 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100268 return 0;
269}
Damien Miller4e270b02010-04-16 15:56:21 +1000270
271int
Damien Millereb8b60e2010-08-31 22:41:14 +1000272key_ec_validate_private(const EC_KEY *key)
273{
Damien Miller86687062014-07-02 15:28:02 +1000274 int r;
Damien Millereb8b60e2010-08-31 22:41:14 +1000275
Damien Miller86687062014-07-02 15:28:02 +1000276 if ((r = sshkey_ec_validate_private(key)) != 0) {
277 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
278 error("%s: %s", __func__, ssh_err(r));
279 return -1;
Damien Millereb8b60e2010-08-31 22:41:14 +1000280 }
Damien Miller86687062014-07-02 15:28:02 +1000281 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +1000282}
Damien Miller86687062014-07-02 15:28:02 +1000283#endif /* WITH_OPENSSL */
Damien Millereb8b60e2010-08-31 22:41:14 +1000284
285void
Damien Miller86687062014-07-02 15:28:02 +1000286key_private_serialize(const Key *key, struct sshbuf *b)
Damien Millereb8b60e2010-08-31 22:41:14 +1000287{
Damien Miller86687062014-07-02 15:28:02 +1000288 int r;
Damien Millereb8b60e2010-08-31 22:41:14 +1000289
Damien Miller86687062014-07-02 15:28:02 +1000290 if ((r = sshkey_private_serialize(key, b)) != 0)
291 fatal("%s: %s", __func__, ssh_err(r));
Damien Millerf0e90602013-12-07 10:40:26 +1100292}
293
294Key *
Damien Miller86687062014-07-02 15:28:02 +1000295key_private_deserialize(struct sshbuf *blob)
Damien Millerf0e90602013-12-07 10:40:26 +1100296{
Damien Miller86687062014-07-02 15:28:02 +1000297 int r;
298 Key *ret = NULL;
Damien Millerf0e90602013-12-07 10:40:26 +1100299
Damien Miller86687062014-07-02 15:28:02 +1000300 if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
301 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
302 error("%s: %s", __func__, ssh_err(r));
Damien Millerf0e90602013-12-07 10:40:26 +1100303 return NULL;
304 }
Damien Miller86687062014-07-02 15:28:02 +1000305 return ret;
306}
Damien Millerf0e90602013-12-07 10:40:26 +1100307
Damien Miller86687062014-07-02 15:28:02 +1000308/* authfile.c */
309
310int
311key_save_private(Key *key, const char *filename, const char *passphrase,
312 const char *comment, int force_new_format, const char *new_format_cipher,
313 int new_format_rounds)
314{
315 int r;
316
317 if ((r = sshkey_save_private(key, filename, passphrase, comment,
318 force_new_format, new_format_cipher, new_format_rounds)) != 0) {
319 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
320 error("%s: %s", __func__, ssh_err(r));
321 return 0;
Damien Millerf0e90602013-12-07 10:40:26 +1100322 }
Damien Miller86687062014-07-02 15:28:02 +1000323 return 1;
324}
325
326int
327key_load_file(int fd, const char *filename, struct sshbuf *blob)
328{
329 int r;
330
djm@openbsd.org1195f4c2015-01-08 10:14:08 +0000331 if ((r = sshkey_load_file(fd, blob)) != 0) {
Damien Miller86687062014-07-02 15:28:02 +1000332 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
333 error("%s: %s", __func__, ssh_err(r));
334 return 0;
335 }
336 return 1;
337}
338
339Key *
340key_load_cert(const char *filename)
341{
342 int r;
343 Key *ret = NULL;
344
345 if ((r = sshkey_load_cert(filename, &ret)) != 0) {
346 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000347 /* Old authfile.c ignored all file errors. */
348 if (r == SSH_ERR_SYSTEM_ERROR)
Damien Miller86687062014-07-02 15:28:02 +1000349 debug("%s: %s", __func__, ssh_err(r));
350 else
351 error("%s: %s", __func__, ssh_err(r));
352 return NULL;
353 }
354 return ret;
355
356}
357
358Key *
359key_load_public(const char *filename, char **commentp)
360{
361 int r;
362 Key *ret = NULL;
363
364 if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
365 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000366 /* Old authfile.c ignored all file errors. */
367 if (r == SSH_ERR_SYSTEM_ERROR)
Damien Miller86687062014-07-02 15:28:02 +1000368 debug("%s: %s", __func__, ssh_err(r));
369 else
370 error("%s: %s", __func__, ssh_err(r));
371 return NULL;
372 }
373 return ret;
374}
375
376Key *
377key_load_private(const char *path, const char *passphrase,
378 char **commentp)
379{
380 int r;
381 Key *ret = NULL;
382
383 if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
384 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000385 /* Old authfile.c ignored all file errors. */
Damien Millerdad9a4a2014-07-18 15:03:49 +1000386 if (r == SSH_ERR_SYSTEM_ERROR ||
387 r == SSH_ERR_KEY_WRONG_PASSPHRASE)
Damien Miller86687062014-07-02 15:28:02 +1000388 debug("%s: %s", __func__, ssh_err(r));
389 else
390 error("%s: %s", __func__, ssh_err(r));
391 return NULL;
392 }
393 return ret;
394}
395
396Key *
397key_load_private_cert(int type, const char *filename, const char *passphrase,
398 int *perm_ok)
399{
400 int r;
401 Key *ret = NULL;
402
403 if ((r = sshkey_load_private_cert(type, filename, passphrase,
404 &ret, perm_ok)) != 0) {
405 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000406 /* Old authfile.c ignored all file errors. */
Damien Millerdad9a4a2014-07-18 15:03:49 +1000407 if (r == SSH_ERR_SYSTEM_ERROR ||
408 r == SSH_ERR_KEY_WRONG_PASSPHRASE)
Damien Miller86687062014-07-02 15:28:02 +1000409 debug("%s: %s", __func__, ssh_err(r));
410 else
411 error("%s: %s", __func__, ssh_err(r));
412 return NULL;
413 }
414 return ret;
415}
416
417Key *
418key_load_private_type(int type, const char *filename, const char *passphrase,
419 char **commentp, int *perm_ok)
420{
421 int r;
422 Key *ret = NULL;
423
424 if ((r = sshkey_load_private_type(type, filename, passphrase,
425 &ret, commentp, perm_ok)) != 0) {
426 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000427 /* Old authfile.c ignored all file errors. */
428 if (r == SSH_ERR_SYSTEM_ERROR ||
Damien Miller86687062014-07-02 15:28:02 +1000429 (r == SSH_ERR_KEY_WRONG_PASSPHRASE))
430 debug("%s: %s", __func__, ssh_err(r));
431 else
432 error("%s: %s", __func__, ssh_err(r));
433 return NULL;
434 }
435 return ret;
436}
437
Damien Miller86687062014-07-02 15:28:02 +1000438int
439key_perm_ok(int fd, const char *filename)
440{
441 return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
442}
443