2017-12-18 02:25:15 +00:00
|
|
|
/* $OpenBSD: key.c,v 1.132 2017/12/18 02:25:15 djm Exp $ */
|
2000-03-26 03:04:51 +00:00
|
|
|
/*
|
2014-07-02 05:28:02 +00:00
|
|
|
* placed in the public domain
|
2000-03-26 03:04:51 +00:00
|
|
|
*/
|
2006-08-05 02:39:39 +00:00
|
|
|
|
2000-03-26 03:04:51 +00:00
|
|
|
#include "includes.h"
|
2001-01-22 05:34:40 +00:00
|
|
|
|
2006-08-05 02:39:39 +00:00
|
|
|
#include <sys/types.h>
|
2014-07-02 05:28:02 +00:00
|
|
|
#include <errno.h>
|
2006-09-01 05:38:36 +00:00
|
|
|
#include <stdarg.h>
|
2006-08-05 01:37:59 +00:00
|
|
|
#include <stdio.h>
|
2015-01-20 23:14:00 +00:00
|
|
|
#include <limits.h>
|
2006-07-24 04:13:33 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
#define SSH_KEY_NO_DEFINE
|
2000-03-26 03:04:51 +00:00
|
|
|
#include "key.h"
|
2010-02-26 20:55:05 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
#include "compat.h"
|
|
|
|
#include "sshkey.h"
|
|
|
|
#include "ssherr.h"
|
|
|
|
#include "log.h"
|
|
|
|
#include "authfile.h"
|
2002-06-23 21:21:30 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
static void
|
|
|
|
fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
|
2000-11-13 11:57:25 +00:00
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
if (r == SSH_ERR_INTERNAL_ERROR ||
|
|
|
|
r == SSH_ERR_ALLOC_FAIL ||
|
|
|
|
(extra_fatal != 0 && r == extra_fatal))
|
|
|
|
fatal("%s: %s", func, ssh_err(r));
|
2000-11-13 11:57:25 +00:00
|
|
|
}
|
|
|
|
|
2013-10-30 11:19:47 +00:00
|
|
|
Key *
|
|
|
|
key_from_blob(const u_char *blob, u_int blen)
|
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
|
|
|
|
|
|
|
if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, 0);
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ret;
|
2013-10-30 11:19:47 +00:00
|
|
|
}
|
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
int
|
|
|
|
key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
|
2000-11-13 11:57:25 +00:00
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
u_char *blob;
|
|
|
|
size_t blen;
|
|
|
|
int r;
|
2000-11-13 11:57:25 +00:00
|
|
|
|
2013-12-04 23:25:51 +00:00
|
|
|
if (blobp != NULL)
|
|
|
|
*blobp = NULL;
|
|
|
|
if (lenp != NULL)
|
|
|
|
*lenp = 0;
|
2014-07-02 05:28:02 +00:00
|
|
|
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, 0);
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
2000-11-13 11:57:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2014-07-02 05:28:02 +00:00
|
|
|
if (blen > INT_MAX)
|
|
|
|
fatal("%s: giant len %zu", __func__, blen);
|
|
|
|
if (blobp != NULL)
|
|
|
|
*blobp = blob;
|
2000-11-13 11:57:25 +00:00
|
|
|
if (lenp != NULL)
|
2014-07-02 05:28:02 +00:00
|
|
|
*lenp = blen;
|
|
|
|
return blen;
|
2000-11-13 11:57:25 +00:00
|
|
|
}
|
|
|
|
|
2013-01-18 00:44:04 +00:00
|
|
|
int
|
2014-07-02 05:28:02 +00:00
|
|
|
key_sign(const Key *key, u_char **sigp, u_int *lenp,
|
2015-12-04 16:41:28 +00:00
|
|
|
const u_char *data, u_int datalen, const char *alg)
|
2000-11-13 11:57:25 +00:00
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
int r;
|
|
|
|
u_char *sig;
|
|
|
|
size_t siglen;
|
|
|
|
|
|
|
|
if (sigp != NULL)
|
|
|
|
*sigp = NULL;
|
|
|
|
if (lenp != NULL)
|
|
|
|
*lenp = 0;
|
|
|
|
if ((r = sshkey_sign(key, &sig, &siglen,
|
2015-12-04 16:41:28 +00:00
|
|
|
data, datalen, alg, datafellows)) != 0) {
|
2014-07-02 05:28:02 +00:00
|
|
|
fatal_on_fatal_errors(r, __func__, 0);
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
2000-11-13 11:57:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-07-02 05:28:02 +00:00
|
|
|
if (siglen > INT_MAX)
|
|
|
|
fatal("%s: giant len %zu", __func__, siglen);
|
|
|
|
if (sigp != NULL)
|
|
|
|
*sigp = sig;
|
|
|
|
if (lenp != NULL)
|
|
|
|
*lenp = siglen;
|
|
|
|
return 0;
|
2000-11-13 11:57:25 +00:00
|
|
|
}
|
|
|
|
|
2002-03-22 01:45:53 +00:00
|
|
|
Key *
|
2003-11-17 10:18:23 +00:00
|
|
|
key_demote(const Key *k)
|
2002-03-22 01:45:53 +00:00
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
2010-02-26 20:55:05 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
if ((r = sshkey_demote(k, &ret)) != 0)
|
|
|
|
fatal("%s: %s", __func__, ssh_err(r));
|
|
|
|
return ret;
|
2010-02-26 20:55:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
key_drop_cert(Key *k)
|
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
int r;
|
|
|
|
|
|
|
|
if ((r = sshkey_drop_cert(k)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, 0);
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
2010-02-26 20:55:05 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2013-12-07 00:24:01 +00:00
|
|
|
return 0;
|
2010-02-26 20:55:05 +00:00
|
|
|
}
|
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
int
|
|
|
|
key_cert_check_authority(const Key *k, int want_host, int require_principal,
|
|
|
|
const char *name, const char **reason)
|
|
|
|
{
|
|
|
|
int r;
|
2010-02-26 20:55:05 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
|
|
|
|
name, reason)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, 0);
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
2010-02-26 20:55:05 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2014-07-02 05:28:02 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2010-02-26 20:55:05 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
/* authfile.c */
|
2010-08-31 12:41:14 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
Key *
|
|
|
|
key_load_cert(const char *filename)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
2010-08-31 12:41:14 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
if ((r = sshkey_load_cert(filename, &ret)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
2014-07-09 03:07:28 +00:00
|
|
|
/* Old authfile.c ignored all file errors. */
|
|
|
|
if (r == SSH_ERR_SYSTEM_ERROR)
|
2014-07-02 05:28:02 +00:00
|
|
|
debug("%s: %s", __func__, ssh_err(r));
|
|
|
|
else
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
|
|
|
return NULL;
|
2010-08-31 12:41:14 +00:00
|
|
|
}
|
|
|
|
return ret;
|
2014-07-02 05:28:02 +00:00
|
|
|
|
2010-08-31 12:41:14 +00:00
|
|
|
}
|
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
Key *
|
|
|
|
key_load_public(const char *filename, char **commentp)
|
2010-08-31 12:41:14 +00:00
|
|
|
{
|
2014-07-02 05:28:02 +00:00
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
2010-08-31 12:41:14 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
2014-07-09 03:07:28 +00:00
|
|
|
/* Old authfile.c ignored all file errors. */
|
|
|
|
if (r == SSH_ERR_SYSTEM_ERROR)
|
2014-07-02 05:28:02 +00:00
|
|
|
debug("%s: %s", __func__, ssh_err(r));
|
|
|
|
else
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
|
|
|
return NULL;
|
2010-08-31 12:41:14 +00:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
Key *
|
|
|
|
key_load_private(const char *path, const char *passphrase,
|
|
|
|
char **commentp)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
|
|
|
|
|
|
|
if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
2014-07-09 03:07:28 +00:00
|
|
|
/* Old authfile.c ignored all file errors. */
|
2014-07-18 05:03:49 +00:00
|
|
|
if (r == SSH_ERR_SYSTEM_ERROR ||
|
|
|
|
r == SSH_ERR_KEY_WRONG_PASSPHRASE)
|
2014-07-02 05:28:02 +00:00
|
|
|
debug("%s: %s", __func__, ssh_err(r));
|
|
|
|
else
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
|
|
|
return NULL;
|
2010-08-31 12:41:14 +00:00
|
|
|
}
|
2014-07-02 05:28:02 +00:00
|
|
|
return ret;
|
2010-08-31 12:41:14 +00:00
|
|
|
}
|
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
Key *
|
|
|
|
key_load_private_cert(int type, const char *filename, const char *passphrase,
|
|
|
|
int *perm_ok)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
|
|
|
|
|
|
|
if ((r = sshkey_load_private_cert(type, filename, passphrase,
|
|
|
|
&ret, perm_ok)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
2014-07-09 03:07:28 +00:00
|
|
|
/* Old authfile.c ignored all file errors. */
|
2014-07-18 05:03:49 +00:00
|
|
|
if (r == SSH_ERR_SYSTEM_ERROR ||
|
|
|
|
r == SSH_ERR_KEY_WRONG_PASSPHRASE)
|
2014-07-02 05:28:02 +00:00
|
|
|
debug("%s: %s", __func__, ssh_err(r));
|
|
|
|
else
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ret;
|
2010-08-31 12:41:14 +00:00
|
|
|
}
|
2013-12-06 23:40:26 +00:00
|
|
|
|
2014-07-02 05:28:02 +00:00
|
|
|
Key *
|
|
|
|
key_load_private_type(int type, const char *filename, const char *passphrase,
|
|
|
|
char **commentp, int *perm_ok)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
Key *ret = NULL;
|
|
|
|
|
|
|
|
if ((r = sshkey_load_private_type(type, filename, passphrase,
|
|
|
|
&ret, commentp, perm_ok)) != 0) {
|
|
|
|
fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
|
2014-07-09 03:07:28 +00:00
|
|
|
/* Old authfile.c ignored all file errors. */
|
|
|
|
if (r == SSH_ERR_SYSTEM_ERROR ||
|
2014-07-02 05:28:02 +00:00
|
|
|
(r == SSH_ERR_KEY_WRONG_PASSPHRASE))
|
|
|
|
debug("%s: %s", __func__, ssh_err(r));
|
|
|
|
else
|
|
|
|
error("%s: %s", __func__, ssh_err(r));
|
|
|
|
return NULL;
|
2013-12-06 23:40:26 +00:00
|
|
|
}
|
2014-07-02 05:28:02 +00:00
|
|
|
return ret;
|
2013-12-06 23:40:26 +00:00
|
|
|
}
|