blob: a05fdd3c07c8c986da0d5be85ab4f69ec110f977 [file] [log] [blame]
djm@openbsd.org04c7e282017-12-18 02:25:15 +00001/* $OpenBSD: key.c,v 1.132 2017/12/18 02:25:15 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
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 Miller86687062014-07-02 15:28:02 +100023static void
24fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
Damien Miller0bc1bd82000-11-13 22:57:25 +110025{
Damien Miller86687062014-07-02 15:28:02 +100026 if (r == SSH_ERR_INTERNAL_ERROR ||
27 r == SSH_ERR_ALLOC_FAIL ||
28 (extra_fatal != 0 && r == extra_fatal))
29 fatal("%s: %s", func, ssh_err(r));
Damien Miller0bc1bd82000-11-13 22:57:25 +110030}
31
Damien Miller4a3a9d42013-10-30 22:19:47 +110032Key *
33key_from_blob(const u_char *blob, u_int blen)
34{
Damien Miller86687062014-07-02 15:28:02 +100035 int r;
36 Key *ret = NULL;
Damien Miller4a3a9d42013-10-30 22:19:47 +110037
Damien Miller86687062014-07-02 15:28:02 +100038 if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
39 fatal_on_fatal_errors(r, __func__, 0);
40 error("%s: %s", __func__, ssh_err(r));
41 return NULL;
Damien Miller0bc1bd82000-11-13 22:57:25 +110042 }
Damien Miller86687062014-07-02 15:28:02 +100043 return ret;
Damien Miller0bc1bd82000-11-13 22:57:25 +110044}
45
46int
Damien Millerf3747bf2013-01-18 11:44:04 +110047key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
48{
Damien Miller86687062014-07-02 15:28:02 +100049 u_char *blob;
50 size_t blen;
51 int r;
52
53 if (blobp != NULL)
54 *blobp = NULL;
55 if (lenp != NULL)
56 *lenp = 0;
57 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
58 fatal_on_fatal_errors(r, __func__, 0);
59 error("%s: %s", __func__, ssh_err(r));
60 return 0;
61 }
62 if (blen > INT_MAX)
63 fatal("%s: giant len %zu", __func__, blen);
64 if (blobp != NULL)
65 *blobp = blob;
66 if (lenp != NULL)
67 *lenp = blen;
68 return blen;
Damien Millerf3747bf2013-01-18 11:44:04 +110069}
70
71int
Damien Miller86687062014-07-02 15:28:02 +100072key_sign(const Key *key, u_char **sigp, u_int *lenp,
markus@openbsd.org76c9fbb2015-12-04 16:41:28 +000073 const u_char *data, u_int datalen, const char *alg)
Damien Miller0bc1bd82000-11-13 22:57:25 +110074{
Damien Miller86687062014-07-02 15:28:02 +100075 int r;
76 u_char *sig;
77 size_t siglen;
78
79 if (sigp != NULL)
80 *sigp = NULL;
81 if (lenp != NULL)
82 *lenp = 0;
83 if ((r = sshkey_sign(key, &sig, &siglen,
markus@openbsd.org76c9fbb2015-12-04 16:41:28 +000084 data, datalen, alg, datafellows)) != 0) {
Damien Miller86687062014-07-02 15:28:02 +100085 fatal_on_fatal_errors(r, __func__, 0);
86 error("%s: %s", __func__, ssh_err(r));
Damien Miller0bc1bd82000-11-13 22:57:25 +110087 return -1;
Damien Miller0bc1bd82000-11-13 22:57:25 +110088 }
Damien Miller86687062014-07-02 15:28:02 +100089 if (siglen > INT_MAX)
90 fatal("%s: giant len %zu", __func__, siglen);
91 if (sigp != NULL)
92 *sigp = sig;
93 if (lenp != NULL)
94 *lenp = siglen;
Damien Miller5be9d9e2013-12-07 11:24:01 +110095 return 0;
Damien Miller0a80ca12010-02-27 07:55:05 +110096}
97
Damien Miller86687062014-07-02 15:28:02 +100098Key *
99key_demote(const Key *k)
100{
101 int r;
102 Key *ret = NULL;
103
104 if ((r = sshkey_demote(k, &ret)) != 0)
105 fatal("%s: %s", __func__, ssh_err(r));
106 return ret;
107}
108
109int
Damien Miller86687062014-07-02 15:28:02 +1000110key_drop_cert(Key *k)
111{
112 int r;
113
114 if ((r = sshkey_drop_cert(k)) != 0) {
115 fatal_on_fatal_errors(r, __func__, 0);
116 error("%s: %s", __func__, ssh_err(r));
117 return -1;
118 }
119 return 0;
120}
121
Damien Miller0a80ca12010-02-27 07:55:05 +1100122int
Damien Miller0a80ca12010-02-27 07:55:05 +1100123key_cert_check_authority(const Key *k, int want_host, int require_principal,
124 const char *name, const char **reason)
125{
Damien Miller86687062014-07-02 15:28:02 +1000126 int r;
Damien Miller0a80ca12010-02-27 07:55:05 +1100127
Damien Miller86687062014-07-02 15:28:02 +1000128 if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
129 name, reason)) != 0) {
130 fatal_on_fatal_errors(r, __func__, 0);
131 error("%s: %s", __func__, ssh_err(r));
Damien Miller0a80ca12010-02-27 07:55:05 +1100132 return -1;
133 }
Damien Miller86687062014-07-02 15:28:02 +1000134 return 0;
135}
136
Damien Miller86687062014-07-02 15:28:02 +1000137/* authfile.c */
138
Damien Miller86687062014-07-02 15:28:02 +1000139Key *
140key_load_cert(const char *filename)
141{
142 int r;
143 Key *ret = NULL;
144
145 if ((r = sshkey_load_cert(filename, &ret)) != 0) {
146 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000147 /* Old authfile.c ignored all file errors. */
148 if (r == SSH_ERR_SYSTEM_ERROR)
Damien Miller86687062014-07-02 15:28:02 +1000149 debug("%s: %s", __func__, ssh_err(r));
150 else
151 error("%s: %s", __func__, ssh_err(r));
152 return NULL;
153 }
154 return ret;
155
156}
157
158Key *
159key_load_public(const char *filename, char **commentp)
160{
161 int r;
162 Key *ret = NULL;
163
164 if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
165 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000166 /* Old authfile.c ignored all file errors. */
167 if (r == SSH_ERR_SYSTEM_ERROR)
Damien Miller86687062014-07-02 15:28:02 +1000168 debug("%s: %s", __func__, ssh_err(r));
169 else
170 error("%s: %s", __func__, ssh_err(r));
171 return NULL;
172 }
173 return ret;
174}
175
176Key *
177key_load_private(const char *path, const char *passphrase,
178 char **commentp)
179{
180 int r;
181 Key *ret = NULL;
182
183 if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
184 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000185 /* Old authfile.c ignored all file errors. */
Damien Millerdad9a4a2014-07-18 15:03:49 +1000186 if (r == SSH_ERR_SYSTEM_ERROR ||
187 r == SSH_ERR_KEY_WRONG_PASSPHRASE)
Damien Miller86687062014-07-02 15:28:02 +1000188 debug("%s: %s", __func__, ssh_err(r));
189 else
190 error("%s: %s", __func__, ssh_err(r));
191 return NULL;
192 }
193 return ret;
194}
195
196Key *
197key_load_private_cert(int type, const char *filename, const char *passphrase,
198 int *perm_ok)
199{
200 int r;
201 Key *ret = NULL;
202
203 if ((r = sshkey_load_private_cert(type, filename, passphrase,
204 &ret, perm_ok)) != 0) {
205 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000206 /* Old authfile.c ignored all file errors. */
Damien Millerdad9a4a2014-07-18 15:03:49 +1000207 if (r == SSH_ERR_SYSTEM_ERROR ||
208 r == SSH_ERR_KEY_WRONG_PASSPHRASE)
Damien Miller86687062014-07-02 15:28:02 +1000209 debug("%s: %s", __func__, ssh_err(r));
210 else
211 error("%s: %s", __func__, ssh_err(r));
212 return NULL;
213 }
214 return ret;
215}
216
217Key *
218key_load_private_type(int type, const char *filename, const char *passphrase,
219 char **commentp, int *perm_ok)
220{
221 int r;
222 Key *ret = NULL;
223
224 if ((r = sshkey_load_private_type(type, filename, passphrase,
225 &ret, commentp, perm_ok)) != 0) {
226 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
Damien Millerd0bb9502014-07-09 13:07:28 +1000227 /* Old authfile.c ignored all file errors. */
228 if (r == SSH_ERR_SYSTEM_ERROR ||
Damien Miller86687062014-07-02 15:28:02 +1000229 (r == SSH_ERR_KEY_WRONG_PASSPHRASE))
230 debug("%s: %s", __func__, ssh_err(r));
231 else
232 error("%s: %s", __func__, ssh_err(r));
233 return NULL;
234 }
235 return ret;
236}