Coverage Report

Created: 2025-11-11 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssh/digest-openssl.c
Line
Count
Source
1
/* $OpenBSD: digest-openssl.c,v 1.9 2020/10/29 02:52:43 djm Exp $ */
2
/*
3
 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include "includes.h"
19
20
#ifdef WITH_OPENSSL
21
22
#include <sys/types.h>
23
#include <limits.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include <openssl/evp.h>
28
29
#include "openbsd-compat/openssl-compat.h"
30
31
#include "sshbuf.h"
32
#include "digest.h"
33
#include "ssherr.h"
34
35
#ifndef HAVE_EVP_SHA256
36
# define EVP_sha256 NULL
37
#endif
38
#ifndef HAVE_EVP_SHA384
39
# define EVP_sha384 NULL
40
#endif
41
#ifndef HAVE_EVP_SHA512
42
# define EVP_sha512 NULL
43
#endif
44
45
struct ssh_digest_ctx {
46
  int alg;
47
  EVP_MD_CTX *mdctx;
48
};
49
50
struct ssh_digest {
51
  int id;
52
  const char *name;
53
  size_t digest_len;
54
  const EVP_MD *(*mdfunc)(void);
55
};
56
57
/* NB. Indexed directly by algorithm number */
58
const struct ssh_digest digests[] = {
59
  { SSH_DIGEST_MD5, "MD5",    16, EVP_md5 },
60
  { SSH_DIGEST_SHA1,  "SHA1",   20, EVP_sha1 },
61
  { SSH_DIGEST_SHA256,  "SHA256", 32, EVP_sha256 },
62
  { SSH_DIGEST_SHA384,  "SHA384", 48, EVP_sha384 },
63
  { SSH_DIGEST_SHA512,  "SHA512", 64, EVP_sha512 },
64
  { -1,     NULL,   0,  NULL },
65
};
66
67
static const struct ssh_digest *
68
ssh_digest_by_alg(int alg)
69
437k
{
70
437k
  if (alg < 0 || alg >= SSH_DIGEST_MAX)
71
0
    return NULL;
72
437k
  if (digests[alg].id != alg) /* sanity */
73
0
    return NULL;
74
437k
  if (digests[alg].mdfunc == NULL)
75
0
    return NULL;
76
437k
  return &(digests[alg]);
77
437k
}
78
79
int
80
ssh_digest_alg_by_name(const char *name)
81
1.62k
{
82
1.62k
  int alg;
83
84
6.17k
  for (alg = 0; digests[alg].id != -1; alg++) {
85
6.17k
    if (strcasecmp(name, digests[alg].name) == 0)
86
1.62k
      return digests[alg].id;
87
6.17k
  }
88
0
  return -1;
89
1.62k
}
90
91
const char *
92
ssh_digest_alg_name(int alg)
93
3.35k
{
94
3.35k
  const struct ssh_digest *digest = ssh_digest_by_alg(alg);
95
96
3.35k
  return digest == NULL ? NULL : digest->name;
97
3.35k
}
98
99
size_t
100
ssh_digest_bytes(int alg)
101
147k
{
102
147k
  const struct ssh_digest *digest = ssh_digest_by_alg(alg);
103
104
147k
  return digest == NULL ? 0 : digest->digest_len;
105
147k
}
106
107
size_t
108
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
109
4.62k
{
110
4.62k
  return EVP_MD_CTX_block_size(ctx->mdctx);
111
4.62k
}
112
113
struct ssh_digest_ctx *
114
ssh_digest_start(int alg)
115
21.4k
{
116
21.4k
  const struct ssh_digest *digest = ssh_digest_by_alg(alg);
117
21.4k
  struct ssh_digest_ctx *ret;
118
119
21.4k
  if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL))
120
0
    return NULL;
121
21.4k
  ret->alg = alg;
122
21.4k
  if ((ret->mdctx = EVP_MD_CTX_new()) == NULL) {
123
0
    free(ret);
124
0
    return NULL;
125
0
  }
126
21.4k
  if (EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) {
127
0
    ssh_digest_free(ret);
128
0
    return NULL;
129
0
  }
130
21.4k
  return ret;
131
21.4k
}
132
133
int
134
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
135
250k
{
136
250k
  if (from->alg != to->alg)
137
0
    return SSH_ERR_INVALID_ARGUMENT;
138
  /* we have bcopy-style order while openssl has memcpy-style */
139
250k
  if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx))
140
0
    return SSH_ERR_LIBCRYPTO_ERROR;
141
250k
  return 0;
142
250k
}
143
144
int
145
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
146
403k
{
147
403k
  if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1)
148
0
    return SSH_ERR_LIBCRYPTO_ERROR;
149
403k
  return 0;
150
403k
}
151
152
int
153
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
154
12.8k
{
155
12.8k
  return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
156
12.8k
}
157
158
int
159
ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
160
257k
{
161
257k
  const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
162
257k
  u_int l = dlen;
163
164
257k
  if (digest == NULL || dlen > UINT_MAX)
165
0
    return SSH_ERR_INVALID_ARGUMENT;
166
257k
  if (dlen < digest->digest_len) /* No truncation allowed */
167
0
    return SSH_ERR_INVALID_ARGUMENT;
168
257k
  if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1)
169
0
    return SSH_ERR_LIBCRYPTO_ERROR;
170
257k
  if (l != digest->digest_len) /* sanity */
171
0
    return SSH_ERR_INTERNAL_ERROR;
172
257k
  return 0;
173
257k
}
174
175
void
176
ssh_digest_free(struct ssh_digest_ctx *ctx)
177
26.6k
{
178
26.6k
  if (ctx == NULL)
179
5.26k
    return;
180
21.4k
  EVP_MD_CTX_free(ctx->mdctx);
181
21.4k
  freezero(ctx, sizeof(*ctx));
182
21.4k
}
183
184
int
185
ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
186
6.73k
{
187
6.73k
  const struct ssh_digest *digest = ssh_digest_by_alg(alg);
188
6.73k
  u_int mdlen;
189
190
6.73k
  if (digest == NULL)
191
0
    return SSH_ERR_INVALID_ARGUMENT;
192
6.73k
  if (dlen > UINT_MAX)
193
0
    return SSH_ERR_INVALID_ARGUMENT;
194
6.73k
  if (dlen < digest->digest_len)
195
0
    return SSH_ERR_INVALID_ARGUMENT;
196
6.73k
  mdlen = dlen;
197
6.73k
  if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL))
198
0
    return SSH_ERR_LIBCRYPTO_ERROR;
199
6.73k
  return 0;
200
6.73k
}
201
202
int
203
ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
204
3.01k
{
205
3.01k
  return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
206
3.01k
}
207
#endif /* WITH_OPENSSL */