blob: 75327d491849abf9a745d6e716d22f5efdbf0815 [file] [log] [blame]
Damien Miller86687062014-07-02 15:28:02 +10001/* $OpenBSD: key.c,v 1.119 2014/06/30 12:54:39 djm 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
Darren Tucker9c16ac92008-06-13 04:40:35 +10008#include <sys/param.h>
Damien Millerd7834352006-08-05 12:39:39 +10009#include <sys/types.h>
Damien Miller86687062014-07-02 15:28:02 +100010#include <errno.h>
Damien Millerded319c2006-09-01 15:38:36 +100011#include <stdarg.h>
Damien Millera7a73ee2006-08-05 11:37:59 +100012#include <stdio.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*
Damien Millerf3747bf2013-01-18 11:44:04 +110043key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
44 u_int *dgst_raw_length)
Damien Miller450a7a12000-03-26 13:04:51 +100045{
Damien Miller86687062014-07-02 15:28:02 +100046 u_char *ret = NULL;
47 size_t dlen;
48 int r;
Damien Miller450a7a12000-03-26 13:04:51 +100049
Damien Miller86687062014-07-02 15:28:02 +100050 if (dgst_raw_length != NULL)
51 *dgst_raw_length = 0;
52 if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0)
53 fatal("%s: %s", __func__, ssh_err(r));
54 if (dlen > INT_MAX)
55 fatal("%s: giant len %zu", __func__, dlen);
56 *dgst_raw_length = dlen;
57 return ret;
Damien Miller450a7a12000-03-26 13:04:51 +100058}
59
Damien Miller0bc1bd82000-11-13 22:57:25 +110060int
Damien Millereba71ba2000-04-29 23:57:08 +100061key_read(Key *ret, char **cpp)
Damien Miller450a7a12000-03-26 13:04:51 +100062{
Damien Miller86687062014-07-02 15:28:02 +100063 return sshkey_read(ret, cpp) == 0 ? 1 : -1;
Damien Miller450a7a12000-03-26 13:04:51 +100064}
Ben Lindstrom836f0e92002-06-23 21:21:30 +000065
Damien Miller450a7a12000-03-26 13:04:51 +100066int
Damien Millerf58b58c2003-11-17 21:18:23 +110067key_write(const Key *key, FILE *f)
Damien Miller450a7a12000-03-26 13:04:51 +100068{
Damien Miller86687062014-07-02 15:28:02 +100069 return sshkey_write(key, f) == 0 ? 1 : 0;
Damien Miller450a7a12000-03-26 13:04:51 +100070}
Ben Lindstrom836f0e92002-06-23 21:21:30 +000071
Damien Miller0bc1bd82000-11-13 22:57:25 +110072Key *
Ben Lindstrom46c16222000-12-22 01:43:59 +000073key_generate(int type, u_int bits)
Damien Miller0bc1bd82000-11-13 22:57:25 +110074{
Damien Miller86687062014-07-02 15:28:02 +100075 int r;
76 Key *ret = NULL;
77
78 if ((r = sshkey_generate(type, bits, &ret)) != 0)
79 fatal("%s: %s", __func__, ssh_err(r));
80 return ret;
Damien Miller0bc1bd82000-11-13 22:57:25 +110081}
82
Damien Miller0a80ca12010-02-27 07:55:05 +110083void
Damien Miller86687062014-07-02 15:28:02 +100084key_cert_copy(const Key *from_key, Key *to_key)
Damien Miller0a80ca12010-02-27 07:55:05 +110085{
Damien Miller86687062014-07-02 15:28:02 +100086 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +110087
Damien Miller86687062014-07-02 15:28:02 +100088 if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
89 fatal("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +110090}
91
Damien Miller0bc1bd82000-11-13 22:57:25 +110092Key *
Damien Millerf58b58c2003-11-17 21:18:23 +110093key_from_private(const Key *k)
Damien Miller0bc1bd82000-11-13 22:57:25 +110094{
Damien Miller86687062014-07-02 15:28:02 +100095 int r;
96 Key *ret = NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +110097
Damien Miller86687062014-07-02 15:28:02 +100098 if ((r = sshkey_from_private(k, &ret)) != 0)
99 fatal("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100100 return ret;
101}
102
Damien Miller86687062014-07-02 15:28:02 +1000103static void
104fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100105{
Damien Miller86687062014-07-02 15:28:02 +1000106 if (r == SSH_ERR_INTERNAL_ERROR ||
107 r == SSH_ERR_ALLOC_FAIL ||
108 (extra_fatal != 0 && r == extra_fatal))
109 fatal("%s: %s", func, ssh_err(r));
Damien Miller0bc1bd82000-11-13 22:57:25 +1100110}
111
Damien Miller4a3a9d42013-10-30 22:19:47 +1100112Key *
113key_from_blob(const u_char *blob, u_int blen)
114{
Damien Miller86687062014-07-02 15:28:02 +1000115 int r;
116 Key *ret = NULL;
Damien Miller4a3a9d42013-10-30 22:19:47 +1100117
Damien Miller86687062014-07-02 15:28:02 +1000118 if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
119 fatal_on_fatal_errors(r, __func__, 0);
120 error("%s: %s", __func__, ssh_err(r));
121 return NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100122 }
Damien Miller86687062014-07-02 15:28:02 +1000123 return ret;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100124}
125
126int
Damien Millerf3747bf2013-01-18 11:44:04 +1100127key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
128{
Damien Miller86687062014-07-02 15:28:02 +1000129 u_char *blob;
130 size_t blen;
131 int r;
132
133 if (blobp != NULL)
134 *blobp = NULL;
135 if (lenp != NULL)
136 *lenp = 0;
137 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
138 fatal_on_fatal_errors(r, __func__, 0);
139 error("%s: %s", __func__, ssh_err(r));
140 return 0;
141 }
142 if (blen > INT_MAX)
143 fatal("%s: giant len %zu", __func__, blen);
144 if (blobp != NULL)
145 *blobp = blob;
146 if (lenp != NULL)
147 *lenp = blen;
148 return blen;
Damien Millerf3747bf2013-01-18 11:44:04 +1100149}
150
151int
Damien Miller86687062014-07-02 15:28:02 +1000152key_sign(const Key *key, u_char **sigp, u_int *lenp,
Damien Millerf58b58c2003-11-17 21:18:23 +1100153 const u_char *data, u_int datalen)
Damien Miller0bc1bd82000-11-13 22:57:25 +1100154{
Damien Miller86687062014-07-02 15:28:02 +1000155 int r;
156 u_char *sig;
157 size_t siglen;
158
159 if (sigp != NULL)
160 *sigp = NULL;
161 if (lenp != NULL)
162 *lenp = 0;
163 if ((r = sshkey_sign(key, &sig, &siglen,
164 data, datalen, datafellows)) != 0) {
165 fatal_on_fatal_errors(r, __func__, 0);
166 error("%s: %s", __func__, ssh_err(r));
Damien Miller0bc1bd82000-11-13 22:57:25 +1100167 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +1100168 }
Damien Miller86687062014-07-02 15:28:02 +1000169 if (siglen > INT_MAX)
170 fatal("%s: giant len %zu", __func__, siglen);
171 if (sigp != NULL)
172 *sigp = sig;
173 if (lenp != NULL)
174 *lenp = siglen;
Damien Miller5be9d9e2013-12-07 11:24:01 +1100175 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +1100176}
177
Damien Miller86687062014-07-02 15:28:02 +1000178int
179key_verify(const Key *key, const u_char *signature, u_int signaturelen,
180 const u_char *data, u_int datalen)
181{
182 int r;
183
184 if ((r = sshkey_verify(key, signature, signaturelen,
185 data, datalen, datafellows)) != 0) {
186 fatal_on_fatal_errors(r, __func__, 0);
187 error("%s: %s", __func__, ssh_err(r));
188 return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
189 }
190 return 1;
191}
192
193Key *
194key_demote(const Key *k)
195{
196 int r;
197 Key *ret = NULL;
198
199 if ((r = sshkey_demote(k, &ret)) != 0)
200 fatal("%s: %s", __func__, ssh_err(r));
201 return ret;
202}
203
204int
205key_to_certified(Key *k, int legacy)
206{
207 int r;
208
209 if ((r = sshkey_to_certified(k, legacy)) != 0) {
210 fatal_on_fatal_errors(r, __func__, 0);
211 error("%s: %s", __func__, ssh_err(r));
212 return -1;
213 }
214 return 0;
215}
216
217int
218key_drop_cert(Key *k)
219{
220 int r;
221
222 if ((r = sshkey_drop_cert(k)) != 0) {
223 fatal_on_fatal_errors(r, __func__, 0);
224 error("%s: %s", __func__, ssh_err(r));
225 return -1;
226 }
227 return 0;
228}
229
Damien Miller0a80ca12010-02-27 07:55:05 +1100230int
231key_certify(Key *k, Key *ca)
232{
Damien Miller86687062014-07-02 15:28:02 +1000233 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +1100234
Damien Miller86687062014-07-02 15:28:02 +1000235 if ((r = sshkey_certify(k, ca)) != 0) {
236 fatal_on_fatal_errors(r, __func__, 0);
237 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100238 return -1;
239 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100240 return 0;
241}
242
243int
244key_cert_check_authority(const Key *k, int want_host, int require_principal,
245 const char *name, const char **reason)
246{
Damien Miller86687062014-07-02 15:28:02 +1000247 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +1100248
Damien Miller86687062014-07-02 15:28:02 +1000249 if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
250 name, reason)) != 0) {
251 fatal_on_fatal_errors(r, __func__, 0);
252 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100253 return -1;
254 }
Damien Miller86687062014-07-02 15:28:02 +1000255 return 0;
256}
257
258#ifdef WITH_OPENSSL
259int
260key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
261{
262 int r;
263
264 if ((r = sshkey_ec_validate_public(group, public)) != 0) {
265 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
266 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100267 return -1;
268 }
Damien Miller0a80ca12010-02-27 07:55:05 +1100269 return 0;
270}
Damien Miller4e270b02010-04-16 15:56:21 +1000271
272int
Damien Millereb8b60e2010-08-31 22:41:14 +1000273key_ec_validate_private(const EC_KEY *key)
274{
Damien Miller86687062014-07-02 15:28:02 +1000275 int r;
Damien Millereb8b60e2010-08-31 22:41:14 +1000276
Damien Miller86687062014-07-02 15:28:02 +1000277 if ((r = sshkey_ec_validate_private(key)) != 0) {
278 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
279 error("%s: %s", __func__, ssh_err(r));
280 return -1;
Damien Millereb8b60e2010-08-31 22:41:14 +1000281 }
Damien Miller86687062014-07-02 15:28:02 +1000282 return 0;
Damien Millereb8b60e2010-08-31 22:41:14 +1000283}
Damien Miller86687062014-07-02 15:28:02 +1000284#endif /* WITH_OPENSSL */
Damien Millereb8b60e2010-08-31 22:41:14 +1000285
286void
Damien Miller86687062014-07-02 15:28:02 +1000287key_private_serialize(const Key *key, struct sshbuf *b)
Damien Millereb8b60e2010-08-31 22:41:14 +1000288{
Damien Miller86687062014-07-02 15:28:02 +1000289 int r;
Damien Millereb8b60e2010-08-31 22:41:14 +1000290
Damien Miller86687062014-07-02 15:28:02 +1000291 if ((r = sshkey_private_serialize(key, b)) != 0)
292 fatal("%s: %s", __func__, ssh_err(r));
Damien Millerf0e90602013-12-07 10:40:26 +1100293}
294
295Key *
Damien Miller86687062014-07-02 15:28:02 +1000296key_private_deserialize(struct sshbuf *blob)
Damien Millerf0e90602013-12-07 10:40:26 +1100297{
Damien Miller86687062014-07-02 15:28:02 +1000298 int r;
299 Key *ret = NULL;
Damien Millerf0e90602013-12-07 10:40:26 +1100300
Damien Miller86687062014-07-02 15:28:02 +1000301 if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
302 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
303 error("%s: %s", __func__, ssh_err(r));
Damien Millerf0e90602013-12-07 10:40:26 +1100304 return NULL;
305 }
Damien Miller86687062014-07-02 15:28:02 +1000306 return ret;
307}
Damien Millerf0e90602013-12-07 10:40:26 +1100308
Damien Miller86687062014-07-02 15:28:02 +1000309/* authfile.c */
310
311int
312key_save_private(Key *key, const char *filename, const char *passphrase,
313 const char *comment, int force_new_format, const char *new_format_cipher,
314 int new_format_rounds)
315{
316 int r;
317
318 if ((r = sshkey_save_private(key, filename, passphrase, comment,
319 force_new_format, new_format_cipher, new_format_rounds)) != 0) {
320 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
321 error("%s: %s", __func__, ssh_err(r));
322 return 0;
Damien Millerf0e90602013-12-07 10:40:26 +1100323 }
Damien Miller86687062014-07-02 15:28:02 +1000324 return 1;
325}
326
327int
328key_load_file(int fd, const char *filename, struct sshbuf *blob)
329{
330 int r;
331
332 if ((r = sshkey_load_file(fd, filename, blob)) != 0) {
333 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
334 error("%s: %s", __func__, ssh_err(r));
335 return 0;
336 }
337 return 1;
338}
339
340Key *
341key_load_cert(const char *filename)
342{
343 int r;
344 Key *ret = NULL;
345
346 if ((r = sshkey_load_cert(filename, &ret)) != 0) {
347 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
348 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
349 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);
366 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
367 debug("%s: %s", __func__, ssh_err(r));
368 else
369 error("%s: %s", __func__, ssh_err(r));
370 return NULL;
371 }
372 return ret;
373}
374
375Key *
376key_load_private(const char *path, const char *passphrase,
377 char **commentp)
378{
379 int r;
380 Key *ret = NULL;
381
382 if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
383 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
384 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
385 debug("%s: %s", __func__, ssh_err(r));
386 else
387 error("%s: %s", __func__, ssh_err(r));
388 return NULL;
389 }
390 return ret;
391}
392
393Key *
394key_load_private_cert(int type, const char *filename, const char *passphrase,
395 int *perm_ok)
396{
397 int r;
398 Key *ret = NULL;
399
400 if ((r = sshkey_load_private_cert(type, filename, passphrase,
401 &ret, perm_ok)) != 0) {
402 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
403 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
404 debug("%s: %s", __func__, ssh_err(r));
405 else
406 error("%s: %s", __func__, ssh_err(r));
407 return NULL;
408 }
409 return ret;
410}
411
412Key *
413key_load_private_type(int type, const char *filename, const char *passphrase,
414 char **commentp, int *perm_ok)
415{
416 int r;
417 Key *ret = NULL;
418
419 if ((r = sshkey_load_private_type(type, filename, passphrase,
420 &ret, commentp, perm_ok)) != 0) {
421 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
422 if ((r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) ||
423 (r == SSH_ERR_KEY_WRONG_PASSPHRASE))
424 debug("%s: %s", __func__, ssh_err(r));
425 else
426 error("%s: %s", __func__, ssh_err(r));
427 return NULL;
428 }
429 return ret;
430}
431
432#ifdef WITH_OPENSSL
433Key *
434key_load_private_pem(int fd, int type, const char *passphrase,
435 char **commentp)
436{
437 int r;
438 Key *ret = NULL;
439
440 if ((r = sshkey_load_private_pem(fd, type, passphrase,
441 &ret, commentp)) != 0) {
442 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
443 error("%s: %s", __func__, ssh_err(r));
444 return NULL;
445 }
446 return ret;
447}
448#endif /* WITH_OPENSSL */
449
450int
451key_perm_ok(int fd, const char *filename)
452{
453 return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
454}
455
456int
457key_in_file(Key *key, const char *filename, int strict_type)
458{
459 int r;
460
461 if ((r = sshkey_in_file(key, filename, strict_type)) != 0) {
462 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
463 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
464 return 0;
465 error("%s: %s", __func__, ssh_err(r));
466 return r == SSH_ERR_KEY_NOT_FOUND ? 0 : -1;
467 }
468 return 1;
Damien Millerf0e90602013-12-07 10:40:26 +1100469}