Coverage Report

Created: 2025-12-14 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssh/sshbuf-getput-crypto.c
Line
Count
Source
1
/*  $OpenBSD: sshbuf-getput-crypto.c,v 1.12 2024/08/15 00:51:51 djm Exp $ */
2
/*
3
 * Copyright (c) 2011 Damien Miller
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
#define SSHBUF_INTERNAL
19
#include "includes.h"
20
21
#include <sys/types.h>
22
#include <stdlib.h>
23
#include <stdio.h>
24
#include <string.h>
25
26
#ifdef WITH_OPENSSL
27
#include <openssl/bn.h>
28
#ifdef OPENSSL_HAS_ECC
29
# include <openssl/ec.h>
30
#endif /* OPENSSL_HAS_ECC */
31
32
#include "ssherr.h"
33
#include "sshbuf.h"
34
35
int
36
sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp)
37
19.8k
{
38
19.8k
  BIGNUM *v;
39
19.8k
  const u_char *d;
40
19.8k
  size_t len;
41
19.8k
  int r;
42
43
19.8k
  if (valp != NULL)
44
19.8k
    *valp = NULL;
45
19.8k
  if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
46
743
    return r;
47
19.1k
  if (valp != NULL) {
48
19.1k
    if ((v = BN_new()) == NULL ||
49
19.1k
        BN_bin2bn(d, len, v) == NULL) {
50
0
      BN_clear_free(v);
51
0
      return SSH_ERR_ALLOC_FAIL;
52
0
    }
53
19.1k
    *valp = v;
54
19.1k
  }
55
19.1k
  return 0;
56
19.1k
}
57
58
#ifdef OPENSSL_HAS_ECC
59
static int
60
get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
61
9.18k
{
62
  /* Refuse overlong bignums */
63
9.18k
  if (len == 0 || len > SSHBUF_MAX_ECPOINT)
64
136
    return SSH_ERR_ECPOINT_TOO_LARGE;
65
  /* Only handle uncompressed points */
66
9.04k
  if (*d != POINT_CONVERSION_UNCOMPRESSED)
67
99
    return SSH_ERR_INVALID_FORMAT;
68
8.95k
  if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
69
25
    return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
70
8.92k
  return 0;
71
8.95k
}
72
73
int
74
sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
75
64
{
76
64
  const u_char *d;
77
64
  size_t len;
78
64
  int r;
79
80
64
  if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
81
0
    return r;
82
64
  if ((r = get_ec(d, len, v, g)) != 0)
83
15
    return r;
84
  /* Skip string */
85
49
  if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
86
    /* Shouldn't happen */
87
0
    SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
88
0
    SSHBUF_ABORT();
89
0
    return SSH_ERR_INTERNAL_ERROR;
90
0
  }
91
49
  return 0;
92
49
}
93
94
int
95
sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
96
9.33k
{
97
9.33k
  EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
98
9.33k
  int r;
99
9.33k
  const u_char *d;
100
9.33k
  size_t len;
101
102
9.33k
  if (pt == NULL) {
103
0
    SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
104
0
    return SSH_ERR_ALLOC_FAIL;
105
0
  }
106
9.33k
  if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
107
209
    EC_POINT_free(pt);
108
209
    return r;
109
209
  }
110
9.12k
  if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
111
245
    EC_POINT_free(pt);
112
245
    return r;
113
245
  }
114
8.87k
  if (EC_KEY_set_public_key(v, pt) != 1) {
115
0
    EC_POINT_free(pt);
116
0
    return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
117
0
  }
118
8.87k
  EC_POINT_free(pt);
119
  /* Skip string */
120
8.87k
  if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
121
    /* Shouldn't happen */
122
0
    SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
123
0
    SSHBUF_ABORT();
124
0
    return SSH_ERR_INTERNAL_ERROR;
125
0
  }
126
8.87k
  return 0;
127
8.87k
}
128
#endif /* OPENSSL_HAS_ECC */
129
130
int
131
sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
132
10.8k
{
133
10.8k
  u_char d[SSHBUF_MAX_BIGNUM + 1];
134
10.8k
  int len = BN_num_bytes(v), prepend = 0, r;
135
136
10.8k
  if (len < 0 || len > SSHBUF_MAX_BIGNUM)
137
0
    return SSH_ERR_INVALID_ARGUMENT;
138
10.8k
  *d = '\0';
139
10.8k
  if (BN_bn2bin(v, d + 1) != len)
140
0
    return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
141
  /* If MSB is set, prepend a \0 */
142
10.8k
  if (len > 0 && (d[1] & 0x80) != 0)
143
5.38k
    prepend = 1;
144
10.8k
  if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
145
0
    explicit_bzero(d, sizeof(d));
146
0
    return r;
147
0
  }
148
10.8k
  explicit_bzero(d, sizeof(d));
149
10.8k
  return 0;
150
10.8k
}
151
152
#ifdef OPENSSL_HAS_ECC
153
int
154
sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
155
8.11k
{
156
8.11k
  u_char d[SSHBUF_MAX_ECPOINT];
157
8.11k
  size_t len;
158
8.11k
  int ret;
159
160
8.11k
  if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
161
8.11k
      NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) {
162
0
    return SSH_ERR_INVALID_ARGUMENT;
163
0
  }
164
8.11k
  if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
165
8.11k
      d, len, NULL) != len) {
166
0
    return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
167
0
  }
168
8.11k
  ret = sshbuf_put_string(buf, d, len);
169
8.11k
  explicit_bzero(d, len);
170
8.11k
  return ret;
171
8.11k
}
172
173
int
174
sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
175
6.82k
{
176
6.82k
  return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
177
6.82k
      EC_KEY_get0_group(v));
178
6.82k
}
179
180
int
181
sshbuf_put_ec_pkey(struct sshbuf *buf, EVP_PKEY *pkey)
182
6.82k
{
183
6.82k
  const EC_KEY *ec;
184
185
6.82k
  if ((ec = EVP_PKEY_get0_EC_KEY(pkey)) == NULL)
186
0
    return SSH_ERR_LIBCRYPTO_ERROR;
187
6.82k
  return sshbuf_put_eckey(buf, ec);
188
6.82k
}
189
#endif /* OPENSSL_HAS_ECC */
190
#endif /* WITH_OPENSSL */